MVC项目首先使用EF 5代码和.NET 4.5.
我正在寻找一种方法来在单个事务上包装dbContext和SimpleMembershipProvider.我尝试使用TransactionScope,但由于成员资格提供程序将打开另一个连接,我得到一个异常(服务器’servername’上的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之后,“Commit”方法是否有可能抛出异常(以某种方式失败)?如果它发生,我们将与孤儿用户结束,因为提供者不是交易的一部分.
我感谢您的任何意见或建议.
快速说明:
有一篇很好的文章解释了为什么我必须将dbContext转换为IObjectContextadapter而不是使用自己的连接属性,但我再也找不到它了.
最佳答案 是的,承诺肯定会抛出.一个简单的例子是连接是否下降.当然还有其他情况.
你有几个选择:
>如果共享连接,则同一数据库上的事务不会升级为分布式.因此,您可以为EF和WebSecurity连接使用一个连接.
>在服务器上启动分布式事务控制器并使用升级.这不是世界上最糟糕的事情.
>不是使用事务,而是更改操作的顺序,以便可以在以后完成或撤消部分成功的操作.例如,检测并清理“孤儿”用户.