Linq To Sql和identity_insert

时间:2009-09-02 17:07:30

标签: c# .net sql-server linq linq-to-sql

我正在尝试在主键为Identity字段的表上执行记录插入。

我试过打电话 mycontext.ExecuteCommand("SET identity_insert myTable ON")
但这没有任何好处。

我在提交更改时收到错误消息IDENTITY_INSERTOFF

在提交更改之前,如何从C#代码中将其转换为ON

修改

我已经读过这是因为ExecuteCommand的代码在不同的会话中执行。

编辑2

有什么方法可以执行一些DDL来从我的C#代码中删除身份规范,进行插入,然后重新启用身份规范?

6 个答案:

答案 0 :(得分:19)

另一种选择是将所有Linq2Sql调用包装在TransactionScope()中。这应该强制它们在同一个连接中运行。

using System.Transactions; // Be sure to add a reference to System.Transactions.dll to your project.

       // ... in a method somewhere ...
       using (System.Transaction.TransactionScope trans = new TransactionScope())
       {
          using(YourDataContext context = new YourDataContext())
          {
             context.ExecuteCommand("SET IDENTITY_INSERT MyTable ON");

             context.ExecuteCommand("yourInsertCommand");

             context.ExecuteCommand("SET IDENTITY_INSERT MyTable OFF");
          }
          trans.Complete();
       }
       // ...

虽然,如果您尝试做类似的事情:

context.ExecuteCommand("SET IDENTITY_INSERT MyTable ON");
context.MyTable.InsertOnSubmit(myTableObject)
context.SubmitChanges()
context.ExecuteCommand("SET IDENTITY_INSERT MyTable OFF");

您可能会遇到其他问题,尤其是在标识列将IsDbGenerated属性设置为true的情况下。 Linq2Sql生成的SQL命令不知道是否包含标识列和值。

答案 1 :(得分:4)

你需要在一个T-SQL代码块中执行所有步骤 - 如果你想打开它,那么这将是非常困难的,然后执行你的LINQ-to-SQL查询,然后转它退了:(

我看到的唯一真正的解决方案是将整个SQL打包成SQL语句并执行:

SET IDENTITY_INSERT MyTable ON

(do your update here)

SET IDENTITY_INSERT MyTable OFF

使用.ExecuteContext()

将其作为单个代码块执行

马克

PS:对于你的编辑#2:不,不幸的是,没有(简单的)方法从列中删除标识,并将其重新打开。 Basicall你必须创建一个没有IDENTITY的新列,复制值,删除IDENTITY列,然后在完成时向后执行相同操作 - 抱歉! : - (

PS#2:这真的引出了一个问题:到底要做什么需要做一个“身份插入”?从应用程序定期?当然 - 您可能会偶尔遇到这种需求,但我总是在SQL Mgmt Studio中单独执行此操作 - 当然不在我的应用程序中.....(只是好奇您的用例/动机是什么)。< / p>

答案 2 :(得分:3)

在执行命令之前,手动打开连接应该足够了。这使得命令在同一会话中运行:

context.Connection.Open();
context.ExecuteCommand("SET IDENTITY_INSERT MyTable ON");
// make changes
// ...
context.SubmitChanges();

答案 3 :(得分:0)

我做的是这样的(Nbuider用于创建实体)。我通常创建所有行,除了标识插入行;这最终完成了。这是测试数据创建,因此不需要事务。

using (var entitiesEfContext = new ContextABC())
{

    var platforms = Builder<Platform>
                                .CreateListOfSize(4)
                                .TheFirst(1)
                                .With(x => x.Description = "Desc1")
                                .With(x => x.IsDeleted = false)
                                .TheNext(1)
                                .With(x => x.Description = "Desc2")
                                .With(x => x.IsDeleted = false)
                                .TheNext(1)
                                .With(x => x.Description = "Desc3")
                                .With(x => x.IsDeleted = false)
                                .TheNext(1)
                                .With(x => x.Description = "Desc4")
                                .With(x => x.IsDeleted = false)
                                .Build();
                foreach (var platform in platforms)
                {
                    entitiesEfContext.Platform.AddObject(platform);
                }
                entitiesEfContext.SaveChanges();

              // the identity insert row (o as id in my case)

               entitiesEfContext.ExecuteStoreCommand("SET IDENTITY_INSERT Platform ON; INSERT INTO [Platform](Platformid,[Description],[IsDeleted],[Created],[Updated]) VALUES (0,'Desc0' ,0 ,getutcdate(),getutcdate());SET IDENTITY_INSERT Platform Off");


              }

答案 4 :(得分:0)

我有同样的错误消息。我通过更改表中主键的属性来解决它。

MyTable.MyId int IDENTITY(1,1) NOT NULL

属性设置MyId(在 dbml 中)

  • 自动生成的值: True ;
  • 自动同步: OnInsert ;
  • 主键: True ;
  • 服务器数据类型: int NOT NULL IDENTITY ;
  • 类型: int ;

答案 5 :(得分:0)

每次添加新记录时,只需简单reseed identity key(带自定义ID),例如:

    using (var desDb = new DesDbContext())
    {
        // del-table-all --------------------------------------------------------
        desDb.Database.ExecuteSqlCommand("DELETE FROM [Products]");

        foreach (var desItem in desList) //desList is List of Product
        {
            // reseed identity key
            desDb.Database.ExecuteSqlCommand("DBCC CHECKIDENT('Products', RESEED," 
                + (desItem.ProductID - 1) + ");");

            // and record
            desDb.Products.Add(desItem);                        

            // save-db                    
            desDb.SaveChanges();

        }
    }