EF Unidirectional foreign key relationship - c#

Provided I have two code-first entities:
User:
public class User
{
public User() {}
[Key]
public int Id {get; set;}
public string Name {get; set;}
public string City {get; set;}
}
City:
public class City
{
public City() {}
[Key]
public string Name {get; set;}
}
How do I make a Foreign key relationship so that the User table will have a City_Name FK, containing a string that has to correspond to one of the Names from the City table? I don't need the reference in the other direction, I just want to make sure that the City_Name in dbo.Users will be from the Name column in the dbo.Cities.
If I just make a migration with a model like that, it will create the City_Name column in dbo.Users and Inserting works fine, but if I want to return a User obj, the City is always null, even if I manually load the City with dbContext.Entry(user).Reference(u => u.City).Load().
Any ideas or insights to what I might be doing wrong, and how is this kind of a relationship achieved in EF ?

Like this:
public class User
{
[Key]
public int Id {get; set;}
public string Name {get; set;}
[ForeignKey("CityMappedToUser")]
public string City_Name {get; set;}
public virtual City CityMappedToUser{get; set;}
}
It's explained pretty good on msdn tbh: https://msdn.microsoft.com/en-us/data/jj713564.aspx

It seems like you need something like this:
public class User
{
public User() {}
[Key]
public int Id {get; set;}
public string Name {get; set;}
public string City_Name {get; set;}
[ForeignKey("City_Name")]
public virtual City City { get; set; }
}
public class City
{
public City() {}
[Key]
public string Name {get; set;}
}

Related

EF Core - Hardcoded Foreign keys

I am trying to work out how to add a reference an object from within EF.
I little hard to explain so I thought I would share a dotnetfiddle example
https://dotnetfiddle.net/4n5Flk
public class ReportConfig
{
[Key]
public int ReportConfigKey {get; set;}
public int ConfigTypeKey {get; set;}
public int ConfigValue {get; set;}
[ForeignKey("ConfigTypeKey")]
public virtual <ConfigType> ConfigType {get; set;}
}
public class ConfigType
{
[Key]
public int ConfigTypeKey {get; set;}
//This can be
//Address
//Car etc etc.
public string ConfigName {get; set;}
}
public class Car
{
[Key]
public int CarId {get; set;}
//other items
}
public class Address
{
[Key]
public AddressId {get; set;}
}
In a nutshell I am trying to create a navigation property to either a car or an address based on the ConfigValue and the ConfigTypeKey
I was thinking to create 2 navigation properties "Car" and "Address" and for both add 2 foreign key's 1 to the object and 1 as a hardcoded reference to ConfigName as Car or Address
is this possible atall
Sorry for the poor explanation.

How to make foreign key inside models for particular column of composite primary key in Entity Framework

class1
{
[key]
public string id1 {get; set;}
[Key]
public string key2 {get; set;}
}
class2
{
[foreignKey("class1")]
public string class1Id{ get; set; }
}
Now here inside class2 I want to use only id1 column of class1 as foreign key.
How to do that?
If you prefer data annotations, just apply the ForeignKey attribute on the navigation property and provide a comma separated list with the FK property name
class1{
[key]
public string id1 {get; set;}
[Key]
public string key2 {get; set;}
}
class2{
public string id1 { get; set;}
public string key2 { get; set;}
[ForeignKey("id1,key2")] // <= the composite FK
public virtual class1 class1{ get; set; }
}
using fluent API configuration is much easier to understand and less error prone:
modelBuilder.Entity< class2>()
.HasRequired(e => e. class1)
.HasForeignKey(e => new { e.id1, e.key2 });

How to define One-to-Zero-to-One relationship with constraint using Fluent API

I have two tables as following
public class Person {
[Key]
public int Id { get; set;}
public string Name {get; set;}
}
and
public class Office {
[key]
public int OfficeId {get; set;}
public string OfficeName { get; set;}
public virtual ICollection<Person> Persons { get; set;}
}
Now I want a relationship in the third table such as
[PersonHasOffice]
| PersonId | OfficeId |
such that the user can have only one or no office.
When I try the following,relationship generated is many to many!
modelBuilder.Entities<Office>
.HasMany(e=>e.Persons)
.WithMany()
.Map(m=>m.ToTable("PersonHasOffice").MapLeftKey("OfficeId").MapRightKey("Id"));
How to get one-to-zero-to-one relationship on the Person side such that either a person has an office or none.
Instead of using extra mapping table, you can add a nullable column OfficeId as a foreign key in Person table.
public class Person
{
[Key]
public int Id { get; set;}
public string Name {get; set;}
[ForeignKey("OfficeId")]
public virtual Office Office {get;set;}
public int? Office Id {get;set;} = null;
}
Add this change to Person class, then run Add-Migration <MigrationName> and run Update-Database from Package Manager Console.

Join dynamic query result with an EntitySet using Linq?

I have the following models:
public class Order
{
public int Id {get; set;}
public int CustomerId {get; set;}
public virtual Category Category {get; set;}
//Many more properties...
}
public class OrderLine
{
public int Id {get; set;}
public int OrderId {get; set;}
public virtual Order Order {get; set;}
public virtual Product Product {get; set;}
//Other properties...
}
I need to get the orders of a particular customer. In order not to retrieve too many information, I created a class:
public class CustomerOrder
{
public int CustomerId {get; set;}
public int OrderId {get; set;}
public string ProductName {get; set;}
public virtual ICollection<OrderLine> {get; set;}
}
I have mapping configuration for the Order and OrderLine classes but none for CustomerOrder as I was thinking that I can project data into this class.
I can:
Use EF to retrieve the data by specifying includes. After the data is retrieved I can project it into the CustomerOrder class. However, will this force EF to retrieve all columns for the main and included tables?
Use a custom SQL query to retrieve the required details from the Order table (maybe directly from a view). The use Linq to join this resultset with OrderLine to have the complete projection. However, will I need to have mapping configuration for the view?
To avoid too many columns and join in the SQL select statement, what is the best way to project the data into CustomerOrder?
You can do it as shown below.You have to do some changes on your models as well.I have done that.Please see that too.
public class Order
{
public int Id {get; set;}
public int CustomerId {get; set;}
public virtual Category Category {get; set;}
public virtual ICollection <OrderLine> OrderLines {get; set;}
//Many more properties...
}
public class OrderLine
{
public int Id {get; set;}
public int OrderId {get; set;}
public virtual Order Order {get; set;}
public virtual Product Product {get; set;}
//Other properties...
}
public class CustomerOrder
{
public int CustomerId {get; set;}
public int OrderId {get; set;}
public string ProductName {get; set;}
public virtual ICollection<OrderLine> OrderLines {get; set;}
}
Final Query :
var orderList = (from order in _context.Orders
from orderLine in order.OrderLines)
select new CustomerOrder
{
CustomerId = order.CustomerId,
OrderId = orderLine.OrderId,
ProductName= orderLine.Product.ProductName,
OrderLines = order.OrderLines
}).AsNoTracking().ToList();
A 1 : No.Only the projected columns will be fetched from the db.
Best Approach : Always use the custom projection (like CustomerOrder).That is the best when we consider the Performance of the EF query.You can use that to send data to the View too (it's like a DTO (Data Transfer Object)).

Foreign key mvc 4 code first c#

How can i add a foreign key to a Model (code first)
i have a model Product which has an ID (primary key) which i want to add to my model order like.
public class Order
{
public int ID {get; set;}
[Required]
public int Total {get; set;}
[Required]
public int ProductId{get; set;}
}
but how can i make the ProductId refer to the id of my Product model like a foreign key?
On Stackoverflow there are alot simmilar questions but all with different answers, but they arent working for me. I really hope someone has a solution or can points me in the right direction with an explanation.
You need to add a navigation property:
public virtual Product Product { get; set; }
So the Order class will look like this:
public class Order
{
public int ID {get; set;}
[Required]
public int Total {get; set;}
[Required]
public int ProductId{get; set;}
[Required]
public virtual Product Product { get; set; }
}
Also, strictly speaking the ProductId property isn't needed once you have the virtual Product property.
You could do something like this:
public class Order
{
public int ID {get; set;}
[Required]
public int Total {get; set;}
[Required]
public int ProductId{get; set;}
[ForeignKey("ProductId")]
public virtual Product Product {get; set;}
}

Categories

Resources