我必须能够设置我试图在我的列表"final_zones"中添加的实体的主键。我有一个控制器构造函数如下:
public UtilController(CFETSContext context)
{
_context = context;
}
......Then in a web api method.........
using (var transaction = _context.Database.BeginTransaction())
{
_context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON");
_context.SaveChanges();
transaction.Commit();
}
using (var transaction = _context.Database.BeginTransaction())
{
_context.Zones.AddRange(final_zones);
_context.SaveChanges(); //ERROR HERE
transaction.Commit();
}
无论我做什么,我似乎不能得到IDENTITY_INSERT打开。我得到以下错误:
{"Cannot insert explicit value for identity column in table 'Zone' when IDENTITY_INSERT is set to OFF."}
我好像就是关不掉它。我可以将实体添加到控制器中的DB中,这样我就知道其他一切都在工作。我试过在没有事务的情况下这样做,结果也是一样的。
_context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON");
_context.Zones.AddRange(final_zones);
_context.SaveChanges();
任何想法?我不知道下一步该做什么。谢谢。
我用以下方法解决了这个问题:
using (var dbContextTransaction = _context.Database.BeginTransaction())
{
try
{
_context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON");
_context.Zones.AddRange(final_zones);
_context.SaveChanges();
dbContextTransaction.Commit();
}
catch (Exception e)
{
dbContextTransaction.Rollback();
}
}
注意:您必须对每个表执行此操作。IDENTITY_INSERT似乎一次只能为一个表设置,所以您可以这样做,也可以在同一事务中将其切换为OFF。
另外,IDENTITY_INSERT必须在事务中,因为它只在事务期间保持打开状态。
SET IDENTITY_INSERT
语句的作用域是一个SQL会话,这实际上相当于在一个打开的连接上发送的一组语句。
然而,默认情况下,EF上下文将为它执行的每个数据库交互语句打开和关闭一个连接。因此在ExecuteSqlCommand
语句之后,连接被关闭,IDENTITY_INSERT
被重置。
现在有一个隐藏的特性,EF 不会关闭连接如果你在上下文执行语句之前打开它。所以如果你这样做…
try
{
_context.Database.Connection.Open();
_context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON");
_context.Zones.AddRange(final_zones);
_context.SaveChanges();
}
finally
{
_context.Database.Connection.Close();
}
…您将注意到IDENTITY_INSERT
设置将在ExecuteSqlCommand
语句中"存活"。