С Entity Framework большую часть времени достаточно SaveChanges()
. Это создает транзакцию или участвует в любой внешней транзакции и выполняет всю необходимую работу в этой транзакции.
Иногда, хотя спаривание SaveChanges(false) + AcceptAllChanges()
полезно.
Самое полезное место для этого - ситуации, когда вы хотите выполнить распределенную транзакцию в двух разных контекстах.
т.е. как то так (плохо):
using (TransactionScope scope = new TransactionScope())
{
//Do something with context1
//Do something with context2
//Save and discard changes
context1.SaveChanges();
//Save and discard changes
context2.SaveChanges();
//if we get here things are looking good.
scope.Complete();
}
Если context1.SaveChanges()
успешно, но context2.SaveChanges()
не удалось, вся распределенная транзакция отменяется. Но, к сожалению, Entity Framework уже отклонил изменения на context1
, поэтому вы не можете воспроизвести или эффективно зарегистрировать ошибку.
Но если вы измените свой код так:
using (TransactionScope scope = new TransactionScope())
{
//Do something with context1
//Do something with context2
//Save Changes but don't discard yet
context1.SaveChanges(false);
//Save Changes but don't discard yet
context2.SaveChanges(false);
//if we get here things are looking good.
scope.Complete();
context1.AcceptAllChanges();
context2.AcceptAllChanges();
}
Хотя вызов SaveChanges(false)
отправляет необходимые команды в базу данных, сам контекст не изменяется, поэтому вы можете сделать это снова, если необходимо, или вы можете запросить ObjectStateManager
, если хотите.
Это означает, что если транзакция фактически выдает исключение, которое вы можете компенсировать, повторяя попытку или регистрируя состояние каждого контекста ObjectStateManager
где-то.
Подробнее см. мой блог .