【问题标题】:Why doesn't SET IDENTITY_INSERT OFF work for me in EF 4.1?为什么 SET IDENTITY_INSERT OFF 在 EF 4.1 中对我不起作用?
【发布时间】:2011-12-04 14:45:49
【问题描述】:

我使用的是 Entity Framework 4.1 Code First,并且我有一个具有 IDENTITY 键的表,因为该表中的所有新条目都应该有一个自动生成的 ID(ID 列称为 AccountNumber)。我需要从该系统的前一个版本导入一些数据 - 这些帐号需要保留。

a previous question 中,我了解到我必须设置 IDENTITY_INSERT ON 才能保留旧帐号。这个想法是,在导入老客户时,我将打开 IDENTITY_INSERT,运行原始 SQL 插入语句,然后将其关闭并使用 EF 实体正常进行。

所以,我有以下代码:

    public const string InsertQuery = "INSERT INTO dbo.Businesses (AccountNumber, Name, Active, CreatedBy, CreatedOn, ModifiedBy, ModifiedOn) VALUES({0}, {1}, {2}, {3}, {4}, {5}, {6})";

...

            dbContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Businesses ON");
            dbContext.Database.ExecuteSqlCommand(InsertQuery, customerData.AccountNumber, customerData.Name, customerData.Active,
                                                 m_userContextManager.GetCurrentUserName(), Now,
                                                 m_userContextManager.GetCurrentUserName(), Now);
            dbContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Businesses OFF");

            // load the entity and map the rest of the attributes
            dbContext.SaveChanges();

当我开始执行第二条语句时,我收到了以下令人发指的错误(因为我刚刚将其设置为 OFF 左右):

Cannot insert explicit value for identity column in table 'Businesses' when IDENTITY_INSERT is set to OFF.

该语句的返回值为-1,但因为the documentation on MSDN for ExecuteSqlCommand 确实不够用,我不知道这意味着什么。如果语句由于某种原因失败,我希望会引发异常。有谁知道这里发生了什么?

【问题讨论】:

    标签: entity-framework ef-code-first


    【解决方案1】:

    ExecuteSqlCommand 将打开连接,执行 sql 然后关闭它。因此,您的下一个命令将使用不同的连接执行。

    您可以做的是使用普通的旧 ADO.net 类在单个事务中插入数据。或者编写数据脚本并作为shown here执行它

    【讨论】:

    • 发出命令后立即关闭连接真是太好了... ;)
    • @JoshKodroff :) 这是设计使然。通常你尽可能延迟打开连接,然后使用它并立即关闭它。
    【解决方案2】:

    没有必要使用普通的旧 ADO.NET;诀窍是将所有内容打包到一个命令中:

    public const string InsertQuery = @"
        SET IDENTITY_INSERT dbo.Businesses ON;
        INSERT INTO dbo.Businesses (AccountNumber, Name, Active, CreatedBy, CreatedOn, ModifiedBy, ModifiedOn) VALUES({0}, {1}, {2}, {3}, {4}, {5}, {6});
        SET IDENTITY_INSERT dbo.Businesses OFF;
    ";
    
    dbContext.Database.ExecuteSqlCommand(InsertQuery, customerData.AccountNumber, customerData.Name, customerData.Active,
                                         m_userContextManager.GetCurrentUserName(), Now,
                                         m_userContextManager.GetCurrentUserName(), Now);
    
    // load the entity and map the rest of the attributes
    dbContext.SaveChanges();
    

    另外,你可以删除SET IDENTITY_INSERT dbo.Businesses OFF(因为IDENTITY_INSERT在命令结束时已经关闭)和dbContext.SaveChanges(),因为ExecuteSqlCommand会立即执行命令;它不会等待 SaveChanges()。

    【讨论】:

    • 在不列出所有属性的情况下保存我的实体的任何方式(再次 - 填充后)???
    • 对不起,我没有听懂你的问题。您的意思是在使用我在回答中描述的方法后立即访问 Business POCO?
    • 我的意思是,插入我在代码中填写的 POCO,而不是一一证明它的属性(如上)。 (当然我也想用SET IDENTITY_INSERT)
    • 类似dbContext.Database.InsertWithIdentity(myPOCO);。可能要求太多了...... :(
    • 我不知道,抱歉。顾名思义,ExecuteSqlCommand 实际上并没有插入任何东西,而是执行了一个命令。虽然在这种情况下命令是 SQL INSERT,但它可以是任何东西。所以是的,你需要为你的命令需要的所有参数提供值。
    猜你喜欢
    • 2022-12-09
    • 1970-01-01
    • 1970-01-01
    • 2017-10-08
    • 1970-01-01
    • 2015-05-10
    • 2021-12-23
    • 2017-06-19
    • 1970-01-01
    相关资源
    最近更新 更多