[英]EF and TPT : the column name is specified more than once in the SET clause
I'm using EF 6 and use a TPT strategy to model my problem. 我正在使用EF 6,并使用TPT策略对问题进行建模。 Rule
is an abstract class. Rule
是一个抽象类。 OvertimeRule
is a concrete class, inheriting from Rule
. OvertimeRule
是一个具体的类,继承自Rule
。
Rule
looks like this : 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
looks like this : OvertimeRule
看起来像这样:
public partial class OvertimeRule : Rule
{
public decimal? ThresholdCoefficient { get; set; }
public decimal? LimitCoefficient { get; set; }
}
When I create a new OvertimeRule
and try to save it, EF first generates this query : 当我创建一个新的OvertimeRule
并尝试保存它时,EF首先生成此查询:
INSERT [dbo].[Rules]([PeriodType], [SortOrder], [StatuteId], [IsActive], [StatuteID])
VALUES (@0, @1, @2, @3, @4, @5, @6, NULL)
As you can see, EF adds an StatuteID
column to the insert, which does not exists anywhere in the solution and makes this an invalid SQL query. 如您所见,EF将StatuteID
列添加到插入中,该列在解决方案中不存在,并使该列成为无效的SQL查询。
SQL then rightfully throws : 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.
然后,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.
The mapping looks like this : 映射如下所示:
modelBuilder.Entity<Rule>().ToTable("Rules", TimmiSchemaName);
modelBuilder.Entity<Rule>().HasRequired(s => s.Statute).WithMany(s => s.Rules).HasForeignKey(r => r.StatuteId);
modelBuilder.Entity<OvertimeRule>().ToTable("OverTimeRules", TimmiSchemaName);
Could anyone tell me what could trigger this behavior ? 谁能告诉我是什么会触发这种行为?
This one was tricky. 这个很棘手。
modelBuilder.Entity<Rule>().HasRequired(s => s.Statute).WithMany().HasForeignKey(r => r.StatuteId);
is actually incorrect, and should have been 实际上是不正确的,应该已经
modelBuilder.Entity<Rule>().HasRequired(s => s.Statute).WithMany(s => s.Rules).HasForeignKey(r => r.StatuteId);
as the property statute.Rules
existed on the other side of the foreign key. 作为属性statute.Rules
存在于外键的另一侧。
Without it, EF tries to auto map the property to a sql column from the Rules table, which he guessed should be StatuteID
. 如果没有它,EF会尝试将属性自动映射到Rules表中的sql列,他猜测应该是StatuteID
。
I see two strange things in the code you provided: 我在您提供的代码中看到了两个奇怪的事情:
1) 1)
modelBuilder.Entity<Rule>().HasRequired(s => s.Statute)...
This part says the property Statute
is required in Rule
, however it's nowhere to be seen. 这部分说Rule
需要属性Statute
,但是无处可寻。 How does this even compile? 怎么编译?
2) 2)
modelBuilder.Entity<Rule>().ToTable("Rules", TimmiSchemaName);
The point of TPT is that you use one of your tables as an abstract class which means you will use that table for the models that derive from it. TPT的要点是,您将一个表用作抽象类,这意味着您将使用该表作为派生自该表的模型。 You shouldn't be able to fetch a Rule , but you can fetch an OverTimeRule
which is a Rule. 你不应该能够获取一个规则 ,但是你可以获取一个OverTimeRule
这是一个规则。 It's also important that the primary key of the derived tables are the exact same primary key of your base table. 派生表的主键与基表完全相同的主键也很重要。 Your context class should look something like this: 您的上下文类应如下所示:
public class MyContext : DbContext
{
public DbSet<Rule> Rules {get; set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<OverTimeRule>().ToTable("OverTimeRules");
...
}
}
Really great article here: http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt 真正很棒的文章: http : //weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.