Member 14795653 Ответов: 1

Как сохранить в базе данных объект, который имеет список другого объекта, который несет его идентификатор в качестве внешнего ключа


Главный Объект
public class Order
{
 [Key]
 public long OrderId { get; set; }
 public string OrderNumber { get; set; }
 public string CustomerId { get; set; }
 public int PaymentMethod { get; set; }
 public decimal GrandTotal { get; set; }

 public virtual ICollection<OrderItem> OrderItems { get; set; }
}


Этот объект имеет OrderId в качестве внешнего ключа
public class OrderItem
{
  [Key]
  public long OrderItemId { get; set; }
  public long OrderId { get; set; }
  public long ItemId { get; set; }
  public long Quantity { get; set; }
  [ForeignKey("ItemId")]
  public virtual Items Items { get; set; }
  [ForeignKey("OrderId")]
  public virtual Order Order { get; set; }

}


Что я уже пробовал:

_context.Order.AddAsync(order);
foreach(var item in order.OrderItems){
 _context.OrderItems.AddAsync(item);
}
_context.SaveChangesAsync();


Это сообщение об ошибке, которое я всегда получал

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_OrderItems_Orders_OrderId". The conflict occurred in database "flavehub", table "dbo.Orders", column 'OrderId'.
The statement has been terminated.

Stack trace
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(DbContext _, ValueTuple`2 parameters)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at flavehub.Repository.ServiceImplementation.OrderItemService.CreateOrderAsync(AddOrderReqObj order) in C:\M_Projs\flavehub\Repository\ServiceImplementation\OrderItemService.cs:line 42

CHill60

Возможно, вам нужно _context.SaveChangesAsync(); после добавления заказа убедитесь, что он действительно существует, прежде чем пытаться сохранить элементы для него

Member 14795653

Я тоже пробовал это делать, но все равно получаю ту же ошибку

1 Ответов

Рейтинг:
2

Afzaal Ahmad Zeeshan

Цитата:
Оператор INSERT конфликтовал с ограничением внешнего ключа "FK_OrderItems_Orders_OrderId". Конфликт произошел в базе данных "flavehub", таблице "dbo.Заказов", столбец 'Кодзаказа'.
Так как ошибка возникает в INSERT я предполагаю, что это происходит потому, что идентификатор существует в таблице. Проверьте наличие идентификатора, а затем либо измените его, либо изящно закройте запрос. Если ваш столбец может иметь повторяющиеся значения для ключа—возможно, потому, что он не используется в качестве первичного ключа—затем обновите схему базы данных и разрешите дубликаты в этом столбце.

Вы ничего не можете сделать, кроме как потерять согласованность ваших данных, отключив эти проверки или пытаясь игнорировать их.

c# - Entity Framework конфликтующее ограничение внешнего ключа - переполнение стека[^]

В вашем коде есть несколько запутанных элементов, прежде всего:
public class Order
{
 [Key]
 public long OrderId { get; set; }
Это таблица, которая, как показано, вызвала проблему. Вы пытаетесь впрыснуть Order объект в базе данных. Это приведет к плохим результатам— как и в данном случае. То, что я делаю с моими таблицами базы данных, выглядит следующим образом:
public class OrderItem
{
  [Key]
  public long OrderItemId { get; set; }
  public long OrderId { get; set; }
  public long ItemId { get; set; }
  public long Quantity { get; set; }
  [ForeignKey("ItemId")]
  public virtual Items Items { get; set; }
  public virtual long ItemId { get; set; }    // <-- this
  [ForeignKey("OrderId")]
  public virtual Order Order { get; set; }
  public virtual long OrderId { get; set; }   // <-- this
}
Теперь в вашем коде вы можете установить значение для OrderId поле в OrderItem чтобы связать сущности—примените свой ForeignKey атрибуты и другие отношения по мере необходимости. Это поможет вам сохранить ссылку, но не заставит Entity Framework случайно подумать, что вы хотите добавить новую запись.

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