Membership.GetUser() within TransactionScope throws TransactionPromotionException

 2023-02-16    376  

问题描述

下面的代码将TransactionAbortedException带有消息,消息”事务已中止”和内部TransactionPromotionException在尝试宣传事务时具有消息”故障”:

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().

Membership.GetUser() within TransactionScope throws TransactionPromotionException

我的连接字符串是:

<add name="MyConnectionString" connectionString="Data Source=localhost\SQLEXPRESS;Initial Catalog=MyDatabase;Integrated Security=True"
   providerName="System.Data.SqlClient" />

我的一切都是 read 告诉我TransactionScope应该毫骂地应用于会员电话.用户存在(否则我期望null返回.)

推荐答案

TransactionScope类掩码例外.最有可能发生的事情是该范围内部的内容失败(抛出异常),并且TransactionAbortedException只是当控制退出using块时发生的副作用.

尝试在try-catch块中缠绕TransactionScope内的所有内容,在catch内部的重新定位,并在那里设置一个断点;你应该能够看到真正的错误是什么.

另一件事,TransactionScope.Complete应该是在包含TransactionScope的using块结束前执行的最后一个语句.在这种情况下,你应该是好的,因为你实际上没有做到任何工作,但是在内部范围内把呼叫放在内部范围内往往会使更多的错误易于代码.


更新:

现在我们知道内部异常是什么(失败促销事务),更清楚正在发生的事情.

问题是在TransactionScope内,您实际上与GetUser打开了另一个数据库连接.会员提供者不知道如何重新使用DataContext您已开放;它必须打开自己的连接,并且当TransactionScope看到这一点时,它试图推广到分布式交易.

它失败,因为您可能在Web服务器,数据库服务器或两者上都有MSDTC禁用.

如果您将打开两个单独的连接,则无法避免分布式事务,因此解决此问题的几种方法:

  1. 移动GetUser呼叫 TransactionScope.也就是说,从成员资格提供程序将用户”读取”用户进入列表,然后在实际需要开始进行修改时启动事务.

  2. 删除GetUser呼叫,并直接从数据库读取用户信息,同一DataContext或至少相同的连接.

  3. 在参与事务的所有服务器上启用DTC(在交易升级时的性能将受到影响).

我认为选择#1在这方面是最好的;您需要从成员提供商读取的数据非常不太可能在阅读它的时间和开始交易时更改.

其他推荐答案

在一个级别,它是正确的;交易始终中止(您不调用Complete()).是确切的代码?

另外,DataContext 外部 TransactionScope让我怀疑它可能正在做一些奇怪的事情,因为在数据上下文首次创建时,事务不是在那里.你尝试过(两者):

  • 反转创建顺序,因此TransactionScope跨越DataContext
  • 呼叫Complete

?

using ( TransactionScope transactionScope = new TransactionScope() )
using ( MyDataContext context = new MyDataContext() )
{
    /* ... */
    transactionScope.Complete();
}

以上所述是小编给大家介绍的Membership.GetUser() within TransactionScope throws TransactionPromotionException,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/33918.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。