EF 代码第一个一对多(使用“通用”表)
Posted
技术标签:
【中文标题】EF 代码第一个一对多(使用“通用”表)【英文标题】:EF Code First One To Many (using a "common" table) 【发布时间】:2014-03-22 01:27:46 【问题描述】:考虑以下示例:
一个人可以有多个地址。一个商店可以有多个地址。 两者都有一个 1:M 到地址表。
使用 EF6,Code First,我如何设置我的实体和映射 (FluentApi) 来支持这一点?根据我使用 EF 1:M 的经验,子表(地址)对于其父表(Person 或 Store)来说是唯一的。我将有一个 Person Table 和一个 PersonAddressTable 具有 1:M 关系。我也会有一个 Store 和 StoreAddress 表,它们有自己的 1:M 关系。不幸的是,现有的数据模型是这样写的。
据我了解,我通过在指向父级的子实体上添加导航属性来定义 1:M 关系。子实体还必须有一个指向父实体的 ID 字段 (FK),并且此 FK 属性必须在子实体上按要求标记。
所以在我的示例中,地址实体将具有
public virtual Person Person get;set;
public int PersonId get;set;
public Virtual Store Store get;set;
public int StoreId get;set;
地址实体映射器将定义:
this.Property(i=>i.PersonId).IsRequired();
this.Property(i=>i.StoreId).IsRequired();
this.HasRequired(p=>p.Person)
.WithMany(c=>c.Addresses)
.HasForeignKey(c=>PersonId);
this.HasRequired(p=>p.Store)
.WithMany(c=>c.Addresses)
.HasForeignKey(c=>c.StoreId);
但根据其父级,子导航属性(Person 或 Store)将为空。当引用 Person 的地址时,Address.Store nav 属性将为 null,当引用商店的地址时,Address.person nav 属性将为 null。
如何正确定义这些关系?
谢谢。
【问题讨论】:
我可能错了,但我认为虚拟属性在您的地址类中是可选的。如果你想要延迟加载,你肯定需要它们。无论如何,如果您正在与一个人打交道,Addresses.Store 是否为 null 有什么关系,如果您正在与商店打交道,Addresses.Person 是否为 null 又有什么关系? 地址类中不应包含 PersonId 和 StoreId。只是虚拟属性很好。 如果地址类上没有PersonId和StoreId,如何在映射代码中指定关系? This.HasRequired(p=>p.Person) .WIthMany(c=>c.Addresses).HasForiegnKey(WHAT_GOES_HERE)? 我也有类似的问题。任何解决方案了吗? ***.com/questions/25042768/… 【参考方案1】:我不确定如何使用 FluentAPI 进行操作,但这是使用 CodeFirst 的一种方法。
注意,Store 和 Person 引用的是 Address,而不是相反。
我将有以下三个课程:
public class AddressModel
public int AddressId get; set;
public string Line1 get; set;
public string Line2 get; set;
public string City get; set;
public string State get; set;
public string Zip get; set;
public class PersonModel
public int PersonId get; set;
public string FirstName get; set;
public string LastName get; set;
public List<AddressModel> Addresses get; set;
public class StoreModel
public int StoreId get; set;
public string StoreName get; set;
public List<AddressModel> Addresses get; set;
【讨论】:
【参考方案2】:首先,您是否在控制基础表或是否被现有表卡住并不清楚。但是,假设您确实可以控制该表并且只想将所有地址映射到单个表,您可以使用 TPH 来执行此操作。
请在下面找到如何设置的示例。
public class AppContext : DbContext
public DbSet<Person> People get; set;
public DbSet<Store> Stores get; set;
public DbSet<Address> Addresses get; set;
public class Person
public Person()
Addresses = new HashSet<PersonAddress>();
public int Id get; set;
public string Name get; set;
public virtual ICollection<PersonAddress> Addresses get; set;
public class Store
public Store()
Addresses = new HashSet<StoreAddress>();
public int Id get; set;
public string StoreName get; set;
public virtual ICollection<StoreAddress> Addresses get; set;
public abstract class Address
public int Id get; set;
public string AddressInformation get; set;
public class PersonAddress : Address
public string PersonAddressInformation get; set;
public class StoreAddress : Address
public string StoreAddressInformation get; set;
由此生成的数据库表如下所示。
【讨论】:
以上是关于EF 代码第一个一对多(使用“通用”表)的主要内容,如果未能解决你的问题,请参考以下文章