【问题标题】:Entity Framework TPC Foreign Key relationships实体框架 TPC 外键关系
【发布时间】:2017-07-20 00:27:26
【问题描述】:

所以我已经实现了每个具体类的表来处理继承层次结构,但是我在导航属性方面遇到了问题。

我的模型结构如下:

我有一个抽象的 BaseEntity 类,有多个派生类,所以:

public abstract class BaseEntity
{
    public virtual ICollection<Comment> Comments { get; set; }
    public EntitytType EntitytType { get; set; }
}

public class FirstDerivedEntity : BaseEntity
{
    //EntitytType == First;
}

public class SecondDerivedEntity : BaseEntity
{
    //EntitytType == Second;
}

public class Comment
{
    public long BaseEntityId { get; set; }
    public EntitytType BaseEntityType { get; set; }
}

public enum EntitytType
{
    First,
    Second
}

这里的 Comments 导航属性不起作用,因为每个派生(具体)类都有自己的一组 Id。在我看来,每个表中的 EntityType 列都可以作为某种鉴别器,但我不知道如何告诉 EF 使用它。

任何帮助将不胜感激!

【问题讨论】:

  • 你应该更具体。你想达到什么目的?
  • 查看this 了解这个常见问题。

标签: c# inheritance entity-framework-6 foreign-keys table-per-class


【解决方案1】:

TPC 工作的解决方案是派生类中的 Id 不仅在它们的表中而且在两个表中都是唯一的。

您可以使用数据库解决方案,例如具有不同初始种子的自动递增主键或 GUID 键(如 SQL Server 中的那些)。

另一种方法是在您的应用程序代码中生成唯一的 GUID 键。 您可以在下面看到如何为实体建模的相同示例代码:

namespace tpc_so
{
    public class tpc_soContext : DbContext
    {
        public tpc_soContext()
        {
        }
        public DbSet<BaseEntity> BaseEntities { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<BaseEntity>().HasKey(b => b.BaseEntityId);
            modelBuilder.Entity<BaseEntity>()
           .Property(b => b.BaseEntityId)
           .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

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

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


            modelBuilder.Entity<Comment>().ToTable("Comments");

            base.OnModelCreating(modelBuilder);
        }

    }
    public abstract class BaseEntity
    {
        public Guid BaseEntityId { get; set; }
        public virtual ICollection<Comment> Comments { get; set; }
    }

    public class FirstDerivedEntity : BaseEntity{}
    public class SecondDerivedEntity : BaseEntity{ }

    public class Comment
    {
        public long CommentId { get; set; }
        public Guid BaseEntityId { get; set; }
        public string Text { get; set; }
    }

}

要创建一些实体,请使用以下代码:

using (var ctx = new tpc_soContext())
{
    ctx.BaseEntities.Add(new FirstDerivedEntity()
    {
        BaseEntityId = Guid.NewGuid(),
        Comments = new List<Comment>() { new Comment() { Text = "First Derived Comment" } }
    });

    ctx.BaseEntities.Add(new SecondDerivedEntity()
    {
        BaseEntityId = Guid.NewGuid(),
        Comments = new List<Comment>() { new Comment() { Text = "Second-Derived Comment" } }
    });

    ctx.SaveChanges();
}

这里有一些 TPC 的好资源:

[Inheritance with EF Code First: Part 3 – Table per Concrete Type (TPC)]

[Entity Framework - Table Per Concrete]

【讨论】:

    猜你喜欢
    • 2020-07-08
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 2022-01-04
    • 2018-07-04
    • 2018-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多