2016-12-24 180 views
0

以下函數AddCountries刪除記錄(如果它們未被使用),然後添加新的或更新現有記錄。被調用時,它工作正常。但是,如果它再次調用(一個新的Web請求被髮送到服務器),它會失敗,並異常實體框架核心 - INSERT失敗

SQLEXCEPTION:當IDENTITY_INSERT設置爲OFF

表「國家」標識列無法插入顯式值

代碼:

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:信息: '?' 已執行的DbCommand(0毫秒)[參數= [@__ c_Code_0 = (尺寸= 2)],的CommandType = '文本',的CommandTimeout = '30' ]
SELECT TOP(1)[X]。[ID],[X]。[代碼],[X]。[名稱]
FROM [國家] AS [X]
其中[x] [代碼] = @__ c_Code_0

Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:信息:已執行的DbCommand(0毫秒)參數= [@ P0 ='? 「 (Size = 2),@ p1 ='?' (Size = 100)],CommandType ='Text',CommandTimeout = '30']
SET NOCOUNT ON;
INSERT INTO [國家]([代碼],[姓名])
VALUES(@ P0,P1 @);
SELECT [ID]
FROM [Country]
WHERE @@ ROWCOUNT = 1 AND [ID] = scope_identity();

調試日誌時失敗:

Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:資料: '?' 時執行的DbCommand(0毫秒)參數= [@__ c_Code_0 = (尺寸= 2)],的CommandType = '文本',的CommandTimeout = '30' ]
SELECT TOP(1)[X]。[ID],[X]。[代碼],[X]。[名稱]
FROM [國家] AS [X]
其中[x] [代碼] = @__ c_Code_0

Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:信息:已執行的DbCommand(2毫秒)參數= [@ P0 ='? ',@ p1 ='?' (Size = 2),@ p2 ='?' (Size = 100)],CommandType ='Text',CommandTimeout = '30']
SET NOCOUNT ON;
INSERT INTO [國家]([ID],[代碼],[姓名])
VALUES(@ P0,P1 @,@ P2);

你可以看到問題 - IDINSERT命令,從而導致它失敗(這是自動生成的主鍵)發送。任何想法爲什麼發生這種情況

回答

0

看到你的地圖沒有更新。在做任何事情之前更新你的地圖模型。

如果要通過代碼設置它: 您不能將特定值插入IDENTITY_INSERT屬性爲Off的列。 你應該在sql: SET IDENTITY_INSERT TABLENAME ON 中用這行代碼設置它,然後更新你的實體模型圖。 然後運行您的應用程序

+0

我不明白你想說什麼。數據模型很好。從代碼中我很清楚,我沒有試圖設置ID字段。對該函數的第一個調用工作正常,第二個失敗......? – Marko

0

我設法解決問題:這裏發生的是SaveChanges()修改了CountryList元素,通過將ID設置爲與數據庫中新創建的行相對應。在這種情況下,這只是Entity Framework的一種不必要的行爲,所以我必須重新創建CountryList,以便每次調用該函數,就是這樣!