我必须能够在我的列表“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."}
我似乎无法让它关闭。我可以在控制器中向我的数据库添加实体,所以我知道其他一切都在工作。我已尝试在没有交易的情况下执行此操作,但结果相同。
_context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON");
_context.Zones.AddRange(final_zones);
_context.SaveChanges();
有什么想法吗?我不知道下一步该尝试什么。感谢。
答案 0 :(得分:4)
我解决了以下问题:
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一次只能为1个表设置,所以你可以这样做,或者在同一个事务中将它切换为OFF。
此外,IDENTITY_INSERT必须在交易中,因为它只在交易期间保持开启状态。
答案 1 :(得分:1)
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
声明。