Membership.GetUser()内的TransactionScope抛出TransactionPromotionException [英] Membership.GetUser() within TransactionScope throws TransactionPromotionException

查看:170
本文介绍了Membership.GetUser()内的TransactionScope抛出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:


  1. 移动的getUser 通话之外的的的TransactionScope 。也就是说,读的网友首先从成员资格提供到一个列表,然后开始交易时,你真正需要开始进行修改。

  1. Move the GetUser calls outside the TransactionScope. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆