DBContext - удалить ожидающие изменения - PullRequest
0 голосов
/ 16 марта 2020

У меня есть приложение MVC с DBContext, созданным один раз для каждого запроса.

В этом запросе я пытаюсь сохранить список заказов

...

foreach (var order in orders)
{
  SaveOrder(order);
}

public SaveOrder(Order order)
{
  _context.Orders.Add(order);
  _context.SaveChanges();
}

...

Однако если первый порядок в списке выдает исключение, то ни один из остальных не сохраняет.

Я попытался перехватить исключение и затем использовать

  _context.Orders.Remove(order)

но при следующем вызове SaveChanges () в контексте БД исходное исключение все еще срабатывает.

Некоторые статьи, похоже, предлагают использовать новый контекст для каждого действия и включать использование утверждение - однако это не дорого (не будет ли создавать новое соединение каждый раз?)

Как правильно это сделать? Есть ли способ удалить все ожидающие изменения?

Спасибо

Ответы [ 2 ]

1 голос
/ 17 марта 2020

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

Так что в вашем случае вызов SaveOrder должен работать следующим образом:

public void SaveOrder(Order order)
{
    try
    {
        _context.Orders.Add(order);
        _context.SaveChanges();
    }
    catch (DbUpdateException ex)
    {
        _context.Entry(order).State = EntityState.Detached; // De-associate from the poisoned order.
        // TODO: Consider logging that this order could not be saved or returning a result to that effect.
    }
}   

Обратите внимание, что если и У сущности заказа есть дочерние элементы, которые были добавлены / обновлены как часть этой операции, вам также необходимо их отсоединить. Т.е.

    catch (DbUpdateException ex)
    {
        _context.Entry(order).State = EntityState.Detached; 
        foreach(var orderLine in order.OrderLines)
        {
            _context.Entry(orderLine).State = EntityState.Detached;
        }
    }

Только для строк, которые были добавлены или иным образом обновлены операцией. Вы не хотели бы отсоединять Order.Customer, если запись о клиенте не была создана / обновлена ​​с помощью этой операции.

Я предпочитаю использовать шаблоны единиц работы, которые будут видеть вставку нового заказа как одну операцию, включающую единица работы. Если я создаю 5 заказов, каждый из которых не зависит друг от друга (1 сбой не влияет на остальные), то это 5 отдельных операций. Раскрутка области видимости DbContext обычно является наиболее безопасным вариантом, чтобы избежать перекрестного «отравления» и не требует значительных затрат. Для операций, которые касаются одних и тех же данных, существуют дополнительные расходы на чтение, хотя они обычно выбираются по сценарию идентификатора ios (Customer By Id, Products By Id и т. Д. c.), Поэтому они имеют низкую стоимость. Чрезмерная путаница с подключенным и отключенным состоянием вокруг заказов может привести к более серьезным проблемам, так как после вызова Save ссылка «заказ» может или не может быть отслеживаемой сущностью.

1 голос
/ 16 марта 2020

Может быть, это поможет

public void SaveOrders()
{
    try
    {
        foreach (var order in orders)
        {
            if (!IsOrderEntryValid(order))
            {
                _invalidOrders.Add(order);
                continue;
            }
            if(!_context.Orders.Exists(/* write your logic to check if the order exists*/))
                _context.Orders.Add(order);

        }
        _context.SaveChanges();
    }
    catch(Exception ex)
    {
        // log the exception
    }
}

public ValidateOrder(Order order)
{
    // do some validations here that would not violate the data format and rules, cause violations and exceptions.
}

Это очень обобщенно c из-за предоставленной информации из вопроса. Я уверен, что вы бы нашли способ проверить и гарантировать, что сохранение данных не вызывает исключений из-за нарушений БД, нарушений ограничений, дубликатов и т. Д. c. Вы узнали бы из исключения, которое оно сгенерировало, и / или должны были его зарегистрировать. Для меня развивающаяся система включает в себя изучение платформы и ее поведения в отношении данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...