C# 4.0 带有SaveChanges和ExecuteStoreCommand的事务性操作

C# 4.0 带有SaveChanges和ExecuteStoreCommand的事务性操作,c#-4.0,entity-framework-4.1,ef-code-first,C# 4.0,Entity Framework 4.1,Ef Code First,我有一个问题想和大家分享。上下文有点混乱,所以我会尽力解释 我需要在多个实体上创建一个事务操作。我正在使用EF CodeFirst,但使用的是一个无法更改的遗留数据库。为了创建一个比数据库提供的更一致的模型,我将数据库信息投影到一个我自己创建的更精细的实体中 由于我需要使用不同的上下文,我最初的想法是使用TransactionScope,这在过去给了我很好的效果。为什么我需要不同的上下文?由于数据库存在各种各样的问题,我不能只在一个操作(UnitOfWork)中进行更新。我需要检索仅在SaveC

我有一个问题想和大家分享。上下文有点混乱,所以我会尽力解释

我需要在多个实体上创建一个事务操作。我正在使用EF CodeFirst,但使用的是一个无法更改的遗留数据库。为了创建一个比数据库提供的更一致的模型,我将数据库信息投影到一个我自己创建的更精细的实体中

由于我需要使用不同的上下文,我最初的想法是使用TransactionScope,这在过去给了我很好的效果。为什么我需要不同的上下文?由于数据库存在各种各样的问题,我不能只在一个操作(UnitOfWork)中进行更新。我需要检索仅在SaveChanges()之后出现的不同ID

我知道,为了使用TransactionScope,我需要在所有操作之间共享相同的连接(我正在这样做,将上下文传递给对象)。但是,当我执行其中一个操作(使用ExecuteStoreCommand)或在第一次保存更改后尝试执行一些更新时,我总是会收到MSDTC错误(对分布式事务的支持被禁用),甚至更罕见,因为卸载的域


我不知道是否有人能帮助我,至少我不知道这一方案的最佳方向。

看看这个答案:

答案正好满足您在多个数据上下文中拥有事务的需要

我发现这篇文章也很有帮助

对于可能需要更简单解决方案的人,当我需要在事务中混合使用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();
}

看起来entityconnection在引擎盖下方打开了新的连接。如果您正在连接到不同的数据库(或正在使用Sql Server 2005),您的事务将被升级为分布式事务。请注意,如果您使用的是Sql Server 2005,事务将自动升级为分布式事务,因为EF将多次打开连接。如果要在多个上下文之间共享同一连接,则应在事务内打开该连接(这将自动在事务中登记该连接),并将该连接传递给上下文。EF不会关闭未打开的连接。请注意,单独打开连接也是防止将事务升级为Sql Server 2005上的分布式事务的一种方法,因为EF不会关闭并重新打开连接。当上下文超出范围时,连接会自动关闭,即在using语句的末尾。
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();
}