Membership.GetUser()内的TransactionScope抛出TransactionPromotionException [英] Membership.GetUser() within TransactionScope throws TransactionPromotionException
问题描述
下面的代码抛出一个 TransactionAbortedException
与消息该交易已中止和内部 TransactionPromotionException
与消息失败的尝试,以促进交易:
The following code throws a TransactionAbortedException
with message "The transaction has aborted" and an inner TransactionPromotionException
with message "Failure while attempting to promote transaction":
using ( TransactionScope transactionScope = new TransactionScope() )
{
try
{
using ( MyDataContext context = new MyDataContext() )
{
Guid accountID = new Guid( Request.QueryString[ "aid" ] );
Account account = ( from a in context.Accounts where a.UniqueID.Equals( accountID ) select a ).SingleOrDefault();
IQueryable < My_Data_Access_Layer.Login > loginList = from l in context.Logins where l.AccountID == account.AccountID select l;
foreach ( My_Data_Access_Layer.Login login in loginList )
{
MembershipUser membershipUser = Membership.GetUser( login.UniqueID );
}
[... lots of DeleteAllOnSubmit() calls]
context.SubmitChanges();
transactionScope.Complete();
}
}
catch ( Exception E )
{
[... reports the exception ...]
}
}
在调用出现的错误Membership.GetUser()
我的连接字符串是:
<add name="MyConnectionString" connectionString="Data Source=localhost\SQLEXPRESS;Initial Catalog=MyDatabase;Integrated Security=True"
providerName="System.Data.SqlClient" />
我什么都的阅读告诉我,的TransactionScope
应该只是得到神奇应用于成员的电话。用户存在(我期望返回null,否则。)
Everything I've read tells me that TransactionScope
should just get magically applied to the Membership calls. The user exists (I'd expect a null return otherwise.)
推荐答案
的的TransactionScope
类口罩例外。最有可能发生的情况是,该范围内的东西是失败(抛出异常),以及 TransactionAbortedException
很简单,就是出现副作用时,控制退出使用
块。
The TransactionScope
class masks exceptions. Most likely what's happening is that something inside that scope is failing (throwing an exception), and the TransactionAbortedException
is simply a side-effect that occurs when control exits the using
block.
尝试包裹在里面的的TransactionScope
一切的try-catch
块,用抓
内再次抛出,并设置一个断点;你应该能够看到真正的错误是什么。
Try wrapping everything inside the TransactionScope
in a try-catch
block, with a rethrow inside the catch
, and set a breakpoint there; you should be able to see what the real error is.
还有一件事, TransactionScope.Complete
应该是最后一条语句年底之前执行使用包含
块。在这种情况下,你可能应该是好的,因为你实际上没有做任何工作之后,但把调用的TransactionScope
完成
内部的内部范围趋向于使更多的bug- 。易代码
One other thing, TransactionScope.Complete
should be the last statement executed before the end of the using
block containing the TransactionScope
. In this case you should probably be alright, since you're not actually doing any work afterward, but putting the call to Complete
inside an inner scope tends to make for more bug-prone code.
更新:
现在我们知道的内部异常是什么(故障促进事务),它更清楚发生了什么事情。
Now that we know what the inner exception is (failure promoting transaction), it's more clear what's going on.
的问题是,<$ C $内C>的TransactionScope 时,实际上是打开了的getUser
另一个数据库连接。成员资格提供程序不知道如何重新使用的DataContext
您已经打开;这有可能打开自己的连接,以及的TransactionScope
看到这个的时候,它试图促进分布式事务。
The problem is that inside the TransactionScope
, you are actually opening up another database connection with GetUser
. The membership provider doesn't know how to re-use the DataContext
you already have open; it has to open its own connection, and when the TransactionScope
sees this, it tries to promote to a distributed transaction.
它的失败,因为你可能已经MSDTC无论是Web服务器,数据库服务器,或两者上禁用。
It's failing because you probably have MSDTC disabled on either the web server, the database server, or both.
有没有办法避免分布式事务,如果你要要打开两个单独的连接,所以真的有解决此问题的几种方式:
There's no way to avoid the distributed transaction if you are going to be opening two separate connections, so there are really a few ways around this issue:
-
移动
的getUser
通话之外的的的TransactionScope
。也就是说,读的网友首先从成员资格提供到一个列表,然后开始交易时,你真正需要开始进行修改。
Move the
GetUser
calls outside theTransactionScope
. That is, "read" the users first from the membership provider into a list, then start the transaction when you actually need to start making modifications.
删除的getUser
通话干脆直接从数据库中读取用户信息,对同一的DataContext
或至少相同的连接。
Remove the GetUser
calls altogether and read the user information directly from the database, on the same DataContext
or at least the same connection.
参与事务(在事务提升性能将受到影响)的所有服务器上启用DTC。
Enable DTC on all servers participating in the transaction (performance will be impacted when a transaction promotes).
我觉得选项#1将是在这种情况下最好的;这是非常不可能的,你需要从成员提供读取的数据将你读它,到时候你开始交易的时间之间改变。
I think that option #1 is going to be the best in this scenario; it's very unlikely that the data you need to read from the membership provider will be changed between the time you read it and the time you begin the transaction.
这篇关于Membership.GetUser()内的TransactionScope抛出TransactionPromotionException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!