因此,我已经实现了Table Per具体的类来处理继承层次结构,但是我在Navigation属性方面遇到了麻烦。
我的模型的结构如下:
我有一个抽象的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
}
这里的Comment导航属性不起作用,因为每个派生的(Concrete)类都有其自己的ID集。在我看来,每个表中的EntityType列都可以用作某种鉴别器,但我不知道如何告诉EF这样使用它。
任何帮助将不胜感激!
最佳答案
为了使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]