考虑以下示例:
一个人可以拥有多个地址。商店可以有多个地址。 两者都有1:M到地址表。
使用EF6,Code First,如何设置实体和映射(FluentApi)以支持此功能?根据我使用EF 1:M的经验,子表(地址)对于其父表(Person或Store)是唯一的。我会有一个Person Table和一个具有1:M关系的PersonAddressTable。我还有一个Store和StoreAddress表,它们有自己的1:M关系。对我来说不幸的是,现有的数据模型是这样编写的。
我的理解是我通过在子实体上添加指向父级的nav属性来定义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)将为null。引用Person的地址时,Address.Store nav属性将为null,并且在引用商店的地址时,Address.person nav属性将为null。
如何正确定义这些关系?
感谢。
答案 0 :(得分: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; }
}
答案 1 :(得分:0)
首先,它不能立即清楚您是否掌控了基础表,或者您是否遇到现有表。但是假设您确实控制了表并且只想将所有地址映射到单个表,则可以使用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; }
}
由此生成的数据库表将如下所示。