繁体   English   中英

将关系映射到实体框架中的基类

[英]Map relationship to base class in Entity Framework

如果我有这样的课程

public class BaseEntity
{
    public int Id {get;set;}
    public DateTime CreatedOn {get;set;}
    public DateTime ModifiedOn {get;set;}

    public IList<ModuleHistory> History {get;set;}
}

public class FirstEntity : BaseEntity
{
    public string FirstEntityProperty {get;set;}
}

public class SecondEntity : BaseEntity
{
    public string SecondEntityProperty {get;set;}
}

public class ModuleHistory
{
    public string Field {get;set;}
    public string FromValue {get;set;}
    public string ToValue {get;set;}

    public BaseEntity Module {get;set;}
}

我想要一张用于 FirstEntities 的表,一张用于 SecondEntities 的表,以及一张用于 ModuleHistories 的表。 我想,ModuleHistory 需要有一个用于 BaseEntityId 的列和一个用于 BaseEntityType(FirstEntity、SecondEntity)的列。 我在这方面的第一次尝试有效,但导致创建了 BaseEntities 表。 EF 是否可以在没有基本实体表的情况下进行映射?

要按具体类型使用表,请使用MapInheritedProperties告诉 EF 基类属性是子类表的一部分。

对于 EntityTypeConfiguration 设置:

public class MyEntityConfiguration : EntityTypeConfiguration<MyEntity>
{
  public MyEntityConfiguration()
  {
    Map(x => x.MapInheritedProperties());
    ToTable("MyEntities");
  }
}

如果您使用模型构建器来设置实体,则:

modelBuilder.Entity<MyEntity>().Map(m =>
{
  m.MapInheritedProperties();
  m.ToTable("MyEntities");
}

在下面编辑(也编辑了上面的示例,MapInheritiedProperties 必须在 ToTable 之前)

如果您想要基类级别的子关系,那么您应该将数据模型构建为每个层次结构的表,而不是每个具体的表,因为表之间的 FK 关系是 1 对 1 的。 ModuleHistory 不能有指向“任一”FirstEntity 或 SecondEntity 的 FK。

有可能让 EF 来映射它,但我不确定是否使用 Code-First 来尝试它.. 使用实体配置:

鉴于原始示例中的类结构:

public class FirstEntityConfiguration : EntityTypeConfiguration<FirstEntity>
{
    public FirstEntityConfiguration()
    {
        Map(x => x.MapInheritedProperties());
        ToTable("FirstEntity");
        HasKey(x => x.Id);

        HasMany(x => x.History)
            .WithOptional(x => (FirstEntity)x.Module)
            .Map(x => x.MapKey("ModuleId"));
    }
}

public class SecondEntityConfiguration : SecondEntityConfiguration<SecondEntity>
{
    public SecondEntityConfiguration()
    {
        Map(x => x.MapInheritedProperties());
        ToTable("SecondEntity");
        HasKey(x => x.Id);

        HasMany(x => x.History)
            .WithOptional(x => (SecondEntity)x.Parent)
            .Map(x => x.MapKey("ModuleId"));
    }
}

public class ModuleHistoryConfiguration : EntityTypeConfiguration<ModuleHistory>
{
    public ModuleHistoryConfiguration()
    {
        ToTable("ModuleHistory");
        HasKey(x => x.Id);
    }
}

// This mapping is needed because ModuleHistory's reference to BaseEntity. EF needs to know there is a Key.
    public class BaseEntityConfiguration : EntityTypeConfiguration<BaseEntity>
    {
        public BaseEntityConfiguration()
        {
            HasKey(x => x.Id);
        }
    }

然后,当您获取 FirstEntity 或 SecondEntity 时,您将收到任何历史记录。

这个实现有几个严重的警告:

  1. 您失去了对模块历史的 FK 约束,因此数据库将不会为孤儿(无级联删除)或历史与父级之间的正确关联提供保护。
  2. 您必须对 TpCC 表上的 PK 负责,以避免在 FirstEntity 和 SecondEntity 之间重复键的可能性。 此处的选项包括表之间的共享序列,或使用 UniqueIdentifier (/w NewSequentialId())

最终,如果您希望基类中的子引用,您可能会更好地使用 Table-per-Hierarchy 配置,否则将历史分成两个类并将关系向上移动到实现类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM