#c# #entity-framework
#c# #entity-framework
Вопрос:
Я пытаюсь найти наиболее правильный способ сохранения списка заказов и одного из платежей с использованием EF6. Я хотел бы знать, верен ли приведенный ниже пример кода, например, если цикл foreach находится в правильном месте?
using (ContextDB db = new ContextDB())
{
foreach (Order item in orders)
{
using (var dbContextTransaction = db.Database.BeginTransaction())
{
try
{
// some logic here to retrieve related payment, etc...
...
db.Orders.Add(item);
db.Payments.Add(pmntRcvd)
db.SaveChanges();
dbContextTransaction.Commit();
}
catch
{
// Code to log the exception
...
}
}
}
}
Ответ №1:
- Вы сохраняете элементы в отдельных транзакциях. Это должно быть очевидно: вы создаете одну транзакцию для каждого элемента.
- В этом нет необходимости
Rollback
. Если вы этого неCommit
сделаете, всегда произойдет откат. Просто удалите весь код обработки ошибок. - Вы проглатываете исключения, чтобы никогда не узнать о проблемах.
- Я не понимаю, почему вы
SaveChanges
так часто звоните. Почему не один раз в конце?
Комментарии:
1. 3. Я обновляю вопрос. Существует код для регистрации исключения и элемента, который его вызвал4. Потому что мне нужно убедиться, что элемент сохраняется после его обработки. Что произойдет, если я вызову SaveChanges() только один раз в конце и возникнет проблема? Или, может быть, я еще не очень хорошо понимаю EF6.
2. (3) вы все равно должны удалить откат и добавить
throw;
. (4) в случае ошибки ничего не будет сохранено. Я понимаю, что это ваше намерение. Вызовите его в конце транзакции или раньше, если необходимо.3. Спасибо за информацию. Я удалил первую db.SaveChanges() и откат. Пока, похоже, все работает так, как ожидалось. Должен ли я также удалить используемую транзакцию или сохранить ее?
4. Ответ сложнее, чем вы думаете. SaveChanges всегда является атомарным, поэтому, если у вас есть только один, вам не нужен tran для атомарности. Но . Пул сетевых подключений имеет недостаток в том, что каждое соединение использует непредсказуемый уровень изоляции при запуске. Рекомендуется всегда использовать явные транзакции с указанным уровнем изоляции.
Ответ №2:
Почему бы не использовать одну транзакцию для всех заказов (например, вывести транзакцию за пределы цикла)?
Если вы готовы принять сценарий, в котором некоторые заказы сохраняются, а некоторые нет, это нормально, но, как сказал #usr, вам нужно сохранить изменения только один раз перед фиксацией транзакции, и вы должны зарегистрировать отклоненные заказы.
Несколько сохранений необходимы, если вам нужно, например, получить идентификатор вновь созданного объекта.
Комментарии:
1. Я попытался поместить код в цикл using transaction, но он выдает исключение после первой фиксации. (Я думаю, это потому, что фиксация обнуляет транзакцию после ее фиксации).
2. Если у вас работает одна транзакция, вам даже не нужно явно создавать транзакцию, потому что EF создает неявную транзакцию для контекста. Тогда ваш код должен выглядеть следующим образом: использование db { for { } db.SaveChanges(); }