以下函数AddCountries
删除记录(如果它们未被使用),然后添加新记录或更新现有记录。调用时,它工作正常。但是,如果再次调用它(将新的Web请求发送到服务器),它将失败并显示异常
SqlException:当IDENTITY_INSERT设置为OFF时,无法在表'Country'中为identity列插入显式值
代码:
public static int AddCountries(ApplicationDbContext db, Country[] CountryList)
{
foreach (Country c in db.Country.ToList())
{
try
{
db.Remove(c);
db.SaveChanges();
}
catch
{
// country in use (foreign key)
UndoChangesDbEntity(db, c);
}
}
int cnt = 0;
foreach (Country c in CountryList)
{
var c_db = db.Country.FirstOrDefault(x => x.Code == c.Code);
if (c_db == null)
{
// adding new
db.Country.Add(c);
}
else if (c_db.Name != c.Name)
{
// change of name
c_db.Name = c.Name;
}
db.SaveChanges(); // *** EXCEPTION ***
cnt++;
}
return cnt;
}
辅助函数:
public static void UndoChangesDbEntity(DbContext context, object entity)
{
var entry = context.Entry(entity);
switch (entry.State)
{
case EntityState.Modified:
entry.State = EntityState.Unchanged;
break;
case EntityState.Added:
entry.State = EntityState.Detached;
break;
case EntityState.Deleted:
entry.Reload();
break;
default:
break;
}
}
成功时调试日志:
Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:Information:Executed DbCommand(0ms)[Parameters = [@__ c_Code_0 ='?' (Size = 2)],CommandType ='Text',CommandTimeout ='30'] SELECT TOP(1)[x]。[ID],[x]。[代码],[x]。[名称]
来自[国家] AS [x]
WHERE [x]。[代码] = @__ c_Code_0Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:Information:Executed DbCommand(0ms)[Parameters = [@ p0 ='?' (大小= 2),@ p1 ='?' (Size = 100)],CommandType ='Text',CommandTimeout = '30'] SET NOCOUNT ON;
插入[国家]([代码],[名称])
价值观(@ p0,@ p1);
SELECT [ID]
来自[国家]
WHERE @@ ROWCOUNT = 1 AND [ID] = scope_identity();
失败时调试日志:
Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:Information:Executed DbCommand(0ms)[Parameters = [@__ c_Code_0 ='?' (Size = 2)],CommandType ='Text',CommandTimeout ='30'] SELECT TOP(1)[x]。[ID],[x]。[代码],[x]。[名称]
来自[国家] AS [x]
WHERE [x]。[代码] = @__ c_Code_0Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:信息:已执行DbCommand(2ms)[Parameters = [@ p0 ='?',@ p1 ='?' (大小= 2),@ p2 ='?' (Size = 100)],CommandType ='Text',CommandTimeout = '30'] SET NOCOUNT ON;
插入[国家]([ID],[代码],[名称])
价值观(@ p0,@ p1,@ p2);
您可以看到问题 - 使用ID
命令发送INSERT
,导致其失败(这是自动生成的主键)。知道为什么会这样吗?
答案 0 :(得分:0)
它看到你的地图没有更新。在做任何更新你的地图模型之前。
如果您想通过代码进行设置:
您无法将特定值插入IDENTITY_INSERT
属性为Off的列中。
你应该在sql中通过这个行代码设置它:
SET IDENTITY_INSERT TABLENAME ON
然后更新您的实体模型映射。
然后运行你的应用程序
答案 1 :(得分:0)
我设法解决了这个问题:这里发生的事情是SaveChanges()修改了CountryList元素,方法是将它的ID设置为与数据库中新创建的行相对应的ID。在这种情况下,这只是Entity Framework的一个不需要的行为,所以我必须为每次调用函数重新创建CountryList,就是这样!