MVC 项目首先使用 EF 5 代码和 .NET 4.5。
我正在寻找一种将 dbContext 和 SimpleMembershipProvider 包装在单个事务中的方法。我尝试使用 TransactionScope,但由于成员资格提供程序将打开另一个连接,我得到一个异常(服务器“服务器名”上的 MSDTC 不可用)。
所以我虽然可以使用 ObjectContext.Connection.BeginTransaction 来代替。成员资格提供者不会成为事务的一部分,但我们的想法是将它放在某个地方,如果它失败,则不会提交事务。
Book bk1 = default(Book);
Book bk2 = default(Book);
object obc = (IObjectContextAdapter)dbContext;
obc.ObjectContext.Connection.Open();
using (tx == obc.ObjectContext.Connection.BeginTransaction) {
bk1 = new Book {
Name = "Book 1 Name",
Location = "USA"
};
dbContext.Books.Add(bk1);
dbContext.SaveChanges();
bk2 = new Book {
Name = "Book 2 Name. Book one Id is: " + bk1.Id,
Location = "USA"
};
dbContext.Books.Add(bk2);
dbContext.SaveChanges();
// this is not part of the transaction,
// however if it trhows an exception the transaction is aborted.
// I'm assuming that if we got here, the commit won't fail...
// But is it really true?
WebSecurity.CreateUserAndAccount("username", "123456");
tx.Commit();
}
无论如何,基于上面的代码:
- 如果 WebSecurity.CreateUserAndAccount 失败,那么整个事情都会失败,这是意料之中的。
- 如果 SaveChanges 方法中的任何一个失败,那么整个事情都会再次失败,因为我们没有到达执行 CreateUserAndAccount 的地方。
这整件事让我想到一个问题:它安全吗?我的意思是:
在我们成功执行 DbContext.SaveChanges 后,“提交”方法是否有可能抛出异常(以某种方式失败)?如果发生这种情况,我们将得到一个孤儿用户,因为提供者不是交易的一部分。
我很感激对此的任何意见或建议。
快速说明:有这篇不错的文章解释了为什么我必须将 dbContext 强制转换为 IObjectContextadapter 而不是使用它自己的连接属性,但我再也找不到它了。