实体框架核心 - INSERT失败

时间:2016-12-24 12:37:10

标签: asp.net-mvc entity-framework exception insert

以下函数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_0

     

Microsoft.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_0

     

Microsoft.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,导致其失败(这是自动生成的主键)。知道为什么会这样吗?

2 个答案:

答案 0 :(得分:0)

它看到你的地图没有更新。在做任何更新你的地图模型之前。

如果您想通过代码进行设置: 您无法将特定值插入IDENTITY_INSERT属性为Off的列中。 你应该在sql中通过这个行代码设置它: SET IDENTITY_INSERT TABLENAME ON 然后更新您的实体模型映射。 然后运行你的应用程序

答案 1 :(得分:0)

我设法解决了这个问题:这里发生的事情是SaveChanges()修改了CountryList元素,方法是将它的ID设置为与数据库中新创建的行相对应的ID。在这种情况下,这只是Entity Framework的一个不需要的行为,所以我必须为每次调用函数重新创建CountryList,就是这样!