2016-12-24 14 views
0

次の関数AddCountriesはレコードが使用されていない場合は削除し、新しいレコードを追加したり、既存のレコードを更新したりします。呼び出されると、正常に動作します。しかし、それはそれは例外Entity Framework Core - INSERTが失敗する

SqlExceptionがで失敗します(新しいWeb要求がサーバーに送信されます)再び呼ばれていた場合:IDENTITY_INSERTがOFFに設定されている場合は「国」テーブルにID列に明示的な値を挿入することはできません

コード:

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(0msと)【パラメータ= [@__ c_Code_0 = (Size = 2)]、CommandType = 'Text'、CommandTimeout = '30 ']
[TOP] [x]。[ID]、[x]。[名前]
。インフォメーション::実行されたDbCommand(0msと)【パラメータ= [@ P0 = '[X]
[X] [コード] = @__ c_Code_0

Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory AS [国] FROM ? ' (サイズ= 2)、@ p1 = '?' (Size = 100)]、CommandType = 'Text'、CommandTimeout = '30']
SET NOCOUNT ON;
INSERT INTO [国]([コード]、[名前])
VALUES(@ p0、@ p1); [国]
@@ ROWCOUNT = 1 AND [ID] = scope_identity();

デバッグログの失敗:

Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:情報: '?' 実行されたDbCommand(0msと)【パラメータ= [@__ c_Code_0 = (Size = 2)]、CommandType = 'Text'、CommandTimeout = '30 ']
[TOP] [x]。[ID]、[x]。[名前]
。インフォメーション::実行されたDbCommand(2ミリ秒)【パラメータ= [@ P0 = '[X]
[X] [コード] = @__ c_Code_0

Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory AS [国] FROM ? '、@ p1 ='? ' (サイズ= 2)、@ p2 = '?' (Size = 100)]、CommandType = 'Text'、CommandTimeout = '30']
SET NOCOUNT ON;
INSERT INTO [国]([ID]、[コード]、[名前])
VALUES(@ p0、@ p1、@ p2);

あなたは問題を見ることができます - IDは、それが(それが自動生成された主キーです)失敗しINSERTコマンドで送信されます。なぜこのようなことが起こるのか?

答えて

0

地図が更新されていないことがわかりました。地図モデルを更新する前に

コードで設定する場合: IDENTITY_INSERTプロパティがオフの列に特定の値を挿入することはできません。 この行コードでsql: SET IDENTITY_INSERT TABLENAME ON に設定し、エンティティモデルマップを更新する必要があります。 次にアプリケーションを実行してください

+0

あなたは何を言っているのか分かりません。データモデルは問題ありません。 IDフィールドを設定しようとしていないことは、コードからはっきりと分かります。関数への最初の呼び出しは正常に動作し、2番目の呼び出しは失敗します...? – Marko

0

ここで起こったことは、SaveChanges()がCountryList要素を、データベースの新しく作成された行に対応するIDに設定することで修正されたことです。この場合、これはEntity Frameworkの望ましくない動作なので、関数呼び出しごとにCountryListを再作成する必要があります。それだけです!

関連する問題