简体   繁体   English

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

[英]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.

相关问题 在 SET 子句中多次指定列名“phoneNumber” - The column name 'phoneNumber' is specified more than once in the SET clause Linq Insert:列名称&#39;&#39;在INSERT的SET子句或列列表中多次指定 - Linq Insert: The column name ' ' is specified more than once in the SET clause or column list of an INSERT 多次指定列名EF代码首次迁移 - Column name is specified more than once EF Code First Migration 每个表中的列名必须唯一。 表“ HumanCustomers”中的列名“ LastName”已多次指定 - Column names in each table must be unique. Column name 'LastName' in table 'HumanCustomers' is specified more than once EF Core - 使用 TPT 方法无法保存超过 1 个实体 - EF Core - Cannot save more than 1 entity with TPT approach 每个表中的列名必须唯一。 表Entity1&#39;中的列名&#39;Id&#39;被多次指定 - Column names in each table must be unique. Column name 'Id' in table Entity1' is specified more than once 每个表中的列名必须唯一。 表“ UserLogins”中的列名“ department_Id”已多次指定 - Column names in each table must be unique. Column name 'department_Id' in table 'UserLogins' is specified more than once Add-Migration一列名称被多次列出 - Add-Migration one column name is listed more than once 内容设置不止一次 - Content is set more than once 使用 EF Core 多次添加相同的实体 object - Adding same entity object more than once with EF Core
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM