Исключение типа "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();
Я также получил аналогичную ошибку при создании метода публикации, но я решил это, выполнив следующие действия.
Убедитесь, что вы включили следующий код в
Конструктор В этом импорте файл интерфейса, к которому принадлежит внешний ключ
Метод 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"); }