我正在尝试在主键为Identity
字段的表上执行记录插入。
我试过打电话
mycontext.ExecuteCommand("SET identity_insert myTable ON")
但这没有任何好处。
我在提交更改时收到错误消息IDENTITY_INSERT
为OFF
。
在提交更改之前,如何从C#代码中将其转换为ON
?
我已经读过这是因为ExecuteCommand的代码在不同的会话中执行。
有什么方法可以执行一些DDL来从我的C#代码中删除身份规范,进行插入,然后重新启用身份规范?
答案 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 中)
答案 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();
}
}