Linq To Sql和identity_insert

我试图在主键是Identity字段的表上进行记录插入。

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

当我提交更改时,我收到一条错误,提示IDENTITY_INSERTOFF

在提交更改之前,如何从C#代码打开它?

编辑

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

编辑2

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

您需要在单个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中单独执行此操作 – 当然不在我的应用程序中…..(只是好奇你的用例/动机是什么)。

另一种选择是将所有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命令不知道包含标识列和值。

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

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

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

 using (var entitiesEfContext = new ContextABC()) { var platforms = Builder .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"); } 

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

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

属性设置MyId(在dbml中

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

每次添加新记录时,只需简单的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(); } }