使用Entity Framework(在我的例子中是代码),我有一个操作,要求我调用SaveChanges来更新DB中的一个对象,然后再次SaveChanges来更新另一个对象。 (我需要第一个SaveChanges来解决EF无法确定首先更新哪个对象的问题。
我尝试过:
using (var transaction = new TransactionScope())
{
// Do something
db.SaveChanges();
// Do something else
db.SaveChanges();
tramsaction.Complete();
}
当我运行它时,我在第二次SaveChanges
调用时收到异常,说“底层提供程序在打开时失败”。内部异常表示我的机器上未启用MSDTC。
现在,我在其他地方看到了描述如何启用MSDTC的帖子,但似乎我还需要启用网络访问等。这听起来像是完全矫枉过正,因为没有涉及其他数据库,更不用说其他服务器。我不想做一些会使我的整个应用程序不那么安全(或更慢)的东西。
当然必须采用更轻量级的方式(理想情况下没有MSDTC)?!
答案 0 :(得分:13)
我知道它的答案很晚,但我觉得分享很有用。
现在在 EF6 中,使用dbContext.Database.BeginTransaction()
using (var context = new BloggingContext())
{
using (var dbContextTransaction = context.Database.BeginTransaction())
{
try
{
// do your changes
context.SaveChanges();
// do another changes
context.SaveChanges();
dbContextTransaction.Commit();
}
catch (Exception)
{
dbContextTransaction.Rollback();
}
}
}
有关详细信息,请查看this
再次进入EF6 Onwards
答案 1 :(得分:8)
这可能是由您的交易中使用的两种不同连接引起的。尝试手动控制操作的连接:
var objectContext = ((IObjectContextAdapter)db).ObjectContext;
try {
object.Context.Connection.Open();
using (var transaction = new TransactionScope()) {
// Do something
db.SaveChanges();
// Do something else
db.SaveChanges();
transaction.Complete();
}
} finally {
objectContext.Connection.Close();
}
答案 2 :(得分:7)
通过调用SaveChanges(),可以将数据持久保存到数据库,而EF则忘记它刚才所做的更改。
诀窍是使用SaveChanges(false),以便更改持久保存到DB,但EF不会忘记它所做的更改,从而使记录/重试成为可能。
var scope = new TransactionScope(
TransactionScopeOption.RequiresNew,
new TransactionOptions() { IsolationLevel = IsolationLevel.Serializable }
);
using (scope)
{
Entities context1 = new Entities();
// Do Stuff
context1.SaveChanges(false);
Entities context2 = new Entities();
// Do Stuff
context2.SaveChanges(false);
scope.Complete();
context1.AcceptAllChanges();
context2.AcceptAllChanges();
}
P.S。只要在transactioncope中打开了多个连接,它就会升级到DTC。
答案 3 :(得分:1)
对于上面选择的最终答案,有一个错字。更正如下:
objectContext.Connection.Open();
另外,需要为System.Data.Entity.Infrastructure和System.Transactions添加引用