EF6 – 使用基类属性在派生类中进行TPH外键映射

我将Entity Framework 6.0.2与现有数据库一起使用,其中标记存储在单个表中,如下所示:

  • Id :int,主键
  • TagType :string,确定标签的类型,“usertag”或“movietag”
  • ItemId :int,包含要引用的项的Id(用户ID或电影ID)

以下类描述了这种情况:

 public class User { public int Id { get; set; } } public class Movie { public int Id { get; set; } } public abstract class Tag { public int Id { get; set; } public int ItemId { get; set; } } public class UserTag : Tag { public virtual User User { get; set; } } public class MovieTag : Tag { public virtual Movie Movie { get; set; } } 

如您所见,我的派生类具有导航属性,这些属性由基类中ItemId属性的值支持。 我的映射如下:

 public class Context : DbContext { public DbSet Tags { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity() .Map(m => m.Requires("TagType").HasValue("usertag")) .Map(m => m.Requires("TagType").HasValue("movietag")); modelBuilder.Entity() .HasRequired(m => m.User).WithMany().HasForeignKey(m => m.ItemId); modelBuilder.Entity() .HasRequired(m => m.Movie).WithMany().HasForeignKey(m => m.ItemId); } } 

现在,当我尝试使用以下代码使用此映射时,我得到一个exception:

 using System.Data.Entity; class Program { static void Main() { using (var db = new Context()) { db.Database.Delete(); db.Database.Initialize(false); } } } 

引发的exception是:

Unhandled Exception: System.InvalidOperationException: The foreign key component 'ItemId' is not a declared property on type 'UserTag'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property

是的, ItemId属性未在UserTag类型上UserTag ,但它inheritance自基类Tag类。 对我而言,似乎这种映射应该是可能的。 这是Entity Framework 6中的错误还是限制?

这是一个限制。 EF与关系数据库的工作方式紧密相关。 您在数据库方面要做的是在单个ItemId列上放置两个外键约束。 数据库中的外部约束不是有条件的,因此无论标记类型如何,记录都将始终使用这两个约束。 这不是你想要的,因为这样的定义总是要求每个标签都存在具有特定Id的用户和电影。

以不同的方式思考它。 如果它按照您尝试定义它的方式工作,则没有理由在子实体中具有UserMovie导航属性 – 在父级中具有单个导航属性就足够了。 您必须在子实体中定义它们,因为它们对于每个实体都是不同的,这也意味着您需要有两个不同的外键。

您需要在其特定标记中包含单独的UserIdMovieId