Транзакционная операция с SaveChanges и ExecuteStoreCommand - PullRequest
5 голосов
/ 23 февраля 2012

У меня есть проблема, которой я хотел бы поделиться.Контекст немного запутанный, поэтому я постараюсь сделать все возможное в объяснении.

Мне нужно создать транзакционную операцию для нескольких сущностей.Я работаю с EF CodeFirst, но с устаревшей базой данных, которую я не могу изменить.Чтобы создать более согласованную модель, чем обеспечивает база данных, я проецирую информацию базы данных на более усовершенствованные объекты, которые я создал сам.

Поскольку мне нужно использовать разные контексты, моей первоначальной идеей было использованиеTransactionScope, который дал мне хорошие результаты в прошлом.Зачем мне нужны разные контексты?Из-за различных проблем с БД я не могу сделать обновления только за одну операцию (UnitOfWork).Мне нужно получить разные идентификаторы, которые появляются только после SaveChanges ().

using (var scope = new TransactionScope())
{
    Operation1();
    Operation2();
    Operation3(uses ExecuteStoreCommand)
    SaveChanges();

    Operation4();
    SaveChanges();
}

Я знаю, что для использования TransactionScope мне нужно использовать одно и то же соединение для всех операций (и я делаюэто, передавая контекст объектам).Тем не менее, когда я выполняю одну из операций (которая использует ExecuteStoreCommand) или пытаюсь выполнить какое-то обновление после первого SaveChanges, я всегда получаю ошибку MSDTC (поддержка распределенных транзакций отключена) или еще реже, незагруженные домены .

Не знаю, может ли кто-нибудь мне помочь, хотя бы узнать, какое направление лучше всего подходит для этого сценария.

Большое спасибо

1 Ответ

7 голосов
/ 11 сентября 2012

Посмотрите на этот ответ:
Entity Framework - Использование транзакций или SaveChanges (false) и AcceptAllChanges ()?
Ответ делает именно то, что вам требуется для транзакции, в нескольких контекстах данных.

Этот пост о Транзакциях и соединениях в Entity Framework 4.0 Я тоже нашел очень полезным.

Для людей, которым может потребоваться более простое решение, вот что я использую, когда мне нужно смешать ExecuteStoreCommand и SaveChanges в транзакции.

using (var dataContext = new ContextEntities())
{
   dataContext.Connection.Open();
   var trx = dataContext.Connection.BeginTransaction();

   var sql = "DELETE TestTable WHERE SomeCondition";
   dataContext.ExecuteStoreCommand(sql);

   var list = CreateMyListOfObjects(); // this could throw an exception
   foreach (var obj in list)
      dataContext.TestTable.AddObject(obj);
   dataContext.SaveChanges(); // this could throw an exception

   trx.Commit();
}
...