EF和TPT:在SET子句中多次指定列名

我正在使用EF 6并使用TPT策略来模拟我的问题。 Rule是一个抽象类。 OvertimeRule是一个inheritance自Rule的具体类。

Rule看起来像这样:

 public abstract class Rule { public int Id { get; set; } public PeriodType PeriodType { get; set; } public int SortOrder { get; set; } public int StatuteId { get; set; } public bool IsActive { get; set; } } 

OvertimeRule看起来像这样:

 public partial class OvertimeRule : Rule { public decimal? ThresholdCoefficient { get; set; } public decimal? LimitCoefficient { get; set; } } 

当我创建一个新的OvertimeRule并尝试保存它时,EF首先生成此查询:

 INSERT [dbo].[Rules]([PeriodType], [SortOrder], [StatuteId], [IsActive], [StatuteID]) VALUES (@0, @1, @2, @3, @4, @5, @6, NULL) 

如您所见,EF向插入添加了一个StatuteID列,该列在解决方案中的任何位置都不存在,并使其成为无效的SQL查询。

SQL然后正确地抛出: The column name 'StatuteId' is specified more than once in the SET clause. A column cannot be assigned more than one value in the same SET clause. Modify the SET clause to make sure that a column is updated only once. If the SET clause updates columns of a view, then the column name 'StatuteId' may appear twice in the view definition. The column name 'StatuteId' is specified more than once in the SET clause. A column cannot be assigned more than one value in the same SET clause. Modify the SET clause to make sure that a column is updated only once. If the SET clause updates columns of a view, then the column name 'StatuteId' may appear twice in the view definition.

映射看起来像这样:

  modelBuilder.Entity().ToTable("Rules", TimmiSchemaName); modelBuilder.Entity().HasRequired(s => s.Statute).WithMany(s => s.Rules).HasForeignKey(r => r.StatuteId); modelBuilder.Entity().ToTable("OverTimeRules", TimmiSchemaName); 

谁能告诉我什么可能触发这种行为?

这个很棘手。

 modelBuilder.Entity().HasRequired(s => s.Statute).WithMany().HasForeignKey(r => r.StatuteId); 

实际上是不正确的,应该是

 modelBuilder.Entity().HasRequired(s => s.Statute).WithMany(s => s.Rules).HasForeignKey(r => r.StatuteId); 

作为属性statute.Rules存在于外键的另一侧。

没有它,EF会尝试从Rules表中自动将属性映射到sql列,他猜测应该是StatuteID

我在你提供的代码中看到两个奇怪的东西:

1)

 modelBuilder.Entity().HasRequired(s => s.Statute)... 

这部分说明Rule要求财产Statute ,但它无处可见。 这怎么编译?

2)

 modelBuilder.Entity().ToTable("Rules", TimmiSchemaName); 

TPT的要点是您使用其中一个表作为抽象类,这意味着您将使用该表作为从中派生的模型。 您应该无法获取规则 ,但您可以获取作为规则的OverTimeRule 。 派生表的主键与基表完全相同的主键也很重要。 您的上下文类应如下所示:

 public class MyContext : DbContext { public DbSet Rules {get; set;} protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity().ToTable("OverTimeRules"); ... } } 

这里真的很棒的文章: http : //weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt