Исключение типа "Microsoft.EntityFrameworkCore.DbUpdateException" возникло в Microsoft.EntityFrameworkCore.dll

У меня проблемы в очень долгое время. Давайте представим этот пример:

public class Coordinate {

     public int id {get;set;}
     public int x {get;set;}
     public int y {get;set;}
}
public class Planet {

     public int id {get;set;}
     public string name {get;set;}
     public Coordinate coordinate {get;set;}
}

Я создал две модели, и модель Planet имеет модель Coordinate в качестве атрибута. Теперь представьте, что где-то в коде я создаю одну координату, и она сохраняется в базе данных. Представьте, что это координата:

Coordinate c = new Coordinate();
c.x = 1;
c.y = 2;

Затем я добавляю его в свою базу данных, и он сохраняется.

Но когда я создаю планету, и я делаю:

planet.coordinate = c;

И затем я пытаюсь добавить его в базу данных, у меня появляется следующая ошибка:

Исключение типа "Microsoft.EntityFrameworkCore.DbUpdateException" произошло в Microsoft.EntityFrameworkCore.dll, но не было обработано в коде пользователя

Дополнительная информация: Произошла ошибка при обновлении записей. Смотрите внутреннее исключение для деталей.

Я знаю, что могу изменить атрибут public Coordinate coordinate в public int coordinate_id но я хочу сделать это с помощью модели координат.

Я использую ASP NET CORE 1.0

Cumps

4 ответа

Решение

Ваша проблема в том, что на данный момент, c уже имеет идентификатор.

С помощью planet.Add планета и все прикрепленные к ней координаты будут установлены в значение "Добавлен" в вашем DbSet, и после вызова SaveChanges будут созданы операторы вставки. (Здесь я предполагаю автоинкремент для вашей колонки и вашего идентификатора)

Когда SaveChanges завершится, EF увидит, что планета находится в базе данных, но Id только что добавленной координаты отличается (он был изменен СУБД, поэтому теперь координата в вашей базе данных дважды, с двумя разными Id), поэтому он будет ожидать, что что-то пошло не так, и выбросит это исключение.

Если у вас нет проблем с дублирующимися записями, установите Id на ноль или 0. В противном случае есть два решения:

-Установите только свойство FK, а не свойство навигации

или же

-Call SaveChanges только один раз (например, просто добавьте планету, однако с добавленной привязкой координат координаты должны привести к тому же результату)

Изучение внутреннего исключения даст вам более подробный взгляд на то, что происходит не так.

Для этого в режиме отладки, когда отображается исключение. Нажмите просмотреть детали и следуйте по дереву, пока не найдете внутреннее исключение.

Могут быть повторяющиеся строки, проблемы первичного ключа или проблемы структуры.

У меня была та же проблема, и я понял, что создавал более одного экземпляра для доступа к базе данных. Итак, решение, которое я принял, заключалось в создании класса, который имел только один доступ.

class SingletonContext {
    private static Context _context;
    public static Context GetInstance() {
        if (_context == null) {
            _context = new Context();
        }
        return _context;
    }
}

И при каждом доступе к уровню базы данных я вызываю GetInstance(), например:

private static Context _context = SingletonContext.GetInstance();

Я также получил аналогичную ошибку при создании метода публикации, но я решил это, выполнив следующие действия.

Убедитесь, что вы включили следующий код в

  1. Конструктор В этом импорте файл интерфейса, к которому принадлежит внешний ключ

  2. Метод HttpPost

             [HttpPost]
     [ProducesResponseType(204)]
     [ProducesResponseType(400)]
     [ProducesResponseType(404)]
    
     //IMPORTANT TO INCLUDE [FromQuery]
     public IActionResult CreateBatch([FromQuery] int trackId, 
      [FromBody] BatchDto batchCreate)
     {
         if(batchCreate == null)
             return BadRequest(ModelState);
    
         var batch = _batchInterface.GetBAtches()
             .Where(c => c.batchName.Trim().ToLower() == 
              batchCreate.batchName
             .TrimEnd().ToLower());
    
         if (batch == null)
             return BadRequest(ModelState);
    
         var batchMap = _mapper.Map<Batch>(batchCreate);
    
         batchMap.track  = _trackInterface.GetTrack(trackId);  //Important
    
         if (!ModelState.IsValid)
             return BadRequest(ModelState);
    
         if(!_batchInterface.CreateBatch(batchMap))
         {
             ModelState.AddModelError("", "Something went in the 
             creation of batch");
             return StatusCode(500, ModelState);
         }
    
         return Ok("Successfully created Batch");
    
     }
    
Другие вопросы по тегам