2016-12-24 4 views
0

Следующая функция AddCountries удаляет записи (если они не используются), а затем добавляет новые или обновляет существующие записи. При вызове он работает нормально. Однако, если он снова позвонил (новый запрос веб отправляется на сервер) он потерпит неудачу с исключениемEntity Framework Core - 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 (0ms) [Параметры = [@__ c_Code_0 = (Size = 2)], CommandType = 'Text', CommandTimeout = '30 ']
SELECT TOP (1) [x]. [ID], [x]. [Код], [x]. [Name]
FROM [Страна] AS [х]
где [х] [Код] = @__ c_Code_0

Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:. информация: Выполняемые DbCommand (0ms) [Параметры = [@ p0 = '? ' (Размер = 2), @ p1 = '?' (Размер = 100)], CommandType = 'Text', CommandTimeout = '30 ']
SET NOCOUNT ON;
INSERT INTO [Страна] ([Код], [Название])
ЦЕННОСТИ (@ p0, @ p1);
SELECT [ID]
FROM [Страна]
WHERE @@ ROWCOUNT = 1 AND [ID] = scope_identity();

журнала отладки при неудачной:

Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory: Информация: '?' Выполняемые DbCommand (0ms) [Параметры = [@__ c_Code_0 = (Size = 2)], CommandType = 'Text', CommandTimeout = '30 ']
SELECT TOP (1) [x]. [ID], [x]. [Код], [x]. [Name]
FROM [Страна] AS [х]
где [х] [Код] = @__ c_Code_0

Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:. информация: Выполняемые DbCommand (2мс) [Параметры = [@ p0 = '? ', @ p1 ='? ' (Размер = 2), @ p2 = '?' (Размер = 100)], CommandType = 'Text', CommandTimeout = '30 ']
SET NOCOUNT ON;
INSERT INTO [Страна] ([ID], [Code], [Name])
ЦЕННОСТИ (@ p0, @ p1, @ p2);

Вы можете увидеть проблему - ID отправляется с INSERT команды, что приводит к его повреждению (это автоматически генерируемый первичный ключ). Любая идея, почему это происходит?

ответ

0

Его видели, что ваша карта не обновляется. перед тем, как сделать что-нибудь, обновите свою модель карты.

Если вы хотите установить его по коду: Вы не можете вставить определенное значение в столбец, в котором находится свойство IDENTITY_INSERT. Вы должны установить его для этого кода строки в sql: SET IDENTITY_INSERT TABLENAME ON , а затем обновите карту модели объекта. затем запустите вашу заявку

+0

Я не понимаю, что вы пытаетесь сказать. Модель данных в порядке. Из кода довольно ясно, что я не пытаюсь установить поле ID. Первый вызов функции работает нормально, а второй - неудачно ...? – Marko

0

Мне удалось решить проблему: что произошло здесь, так это то, что SaveChanges() изменил элементы CountryList, установив его идентификаторы для тех, которые соответствуют вновь созданным строкам в базе данных. В этом случае это просто нежелательное поведение Entity Framework, поэтому мне нужно воссоздать CountryList для каждого вызова функции, и все!