【问题标题】:EF Code First One To Many (using a "common" table)EF 代码第一个一对多(使用“通用”表)
【发布时间】: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)?
  • 我也有类似的问题。任何解决方案了吗? stackoverflow.com/questions/25042768/…

标签: c# entity-framework ef-code-first


【解决方案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; }
        }
    

    由此生成的数据库表如下所示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多