在 TransactionScope 中登记 System.Web.Providers

发布于 2024-12-11 13:29:05 字数 4750 浏览 0 评论 0原文

我们正在尝试使用 System.Transactions.TransactionScope 将 System.Web.Providers 成员资格管理集成到事务中,并不断收到以下错误消息:

The operation is not valid for the state of the transaction.

包裹在异常中,并带有以下更令人困惑的消息:

The provider did not return a ProviderManifestToken string.

在有人询问之前,是的,我们有验证连接字符串是否正确,并且我们用于连接到数据库的用户是否具有适当的权限。如果我们尝试从 TransactionScope 块中调用 Membership.CreateUser(),它就会起作用。将其放入 TransactionScope 中,但会失败。

关于通用提供者的信息似乎少得惊人。您看到的几乎都是 NuGet 页面的链接和 Scott Hanselman 六月份的博客文章。

有人知道如何让 System.Web.Providers 参与事务吗?

谢谢。

这是完整的堆栈跟踪,以防有帮助:

System.Data.ProviderIncompatibleException was unhandled by user code
  Message=The provider did not return a ProviderManifestToken string.
  Source=System.Data.Entity
  StackTrace:
       at System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection)
       at System.Web.Providers.Entities.ModelHelper.GetStorageMetadata(String providerName, DbConnection connection, String ssdl)
       at System.Web.Providers.Entities.ModelHelper.CreateMetadataWorkspace(String providerName, DbConnection connection, String csdl, String ssdl, String msl)
       at System.Web.Providers.Entities.ModelHelper.CreateEntityConnection(ConnectionStringSettings setting, String csdl, String ssdl, String msl)
       at System.Web.Providers.Entities.ModelHelper.CreateMembershipEntities(ConnectionStringSettings setting)
       at System.Web.Providers.DefaultMembershipProvider.Membership_CreateUser(String applicationName, String userName, String password, String salt, String email, String passwordQuestion, String passwordAnswer, Boolean isApproved, DateTime& createDate, Boolean uniqueEmail, Int32 passwordFormat, Object& providerUserKey)
       at System.Web.Providers.DefaultMembershipProvider.CreateUser(String username, String password, String email, String passwordQuestion, String passwordAnswer, Boolean isApproved, Object providerUserKey, MembershipCreateStatus& status)
       at System.Web.Security.Membership.CreateUser(String username, String password, String email, String passwordQuestion, String passwordAnswer, Boolean isApproved, Object providerUserKey, MembershipCreateStatus& status)
       at WcfLoginRegister.RegistrationService.RegisterUser(RegisterUserRequest request) in C:\Users\rmacgrogan\dev\pallas\parthenon\sandbox\FbEntityTypeTester\WcfLoginRegister\RegistrationService.svc.cs:line 43
       at SyncInvokeRegisterUser(Object , Object[] , Object[] )
       at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
       at     System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
  InnerException: System.Transactions.TransactionException
       Message=The operation is not valid for the state of the transaction.
       Source=System.Transactions
       StackTrace:
            at     System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction)
            at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
            at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
            at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
            at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
            at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
            at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
            at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
            at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
            at System.Data.SqlClient.SqlConnection.Open()
            at System.Data.SqlClient.SqlProviderServices.UsingConnection(SqlConnection sqlConnection, Action`1 act)
            at System.Data.SqlClient.SqlProviderServices.UsingMasterConnection(SqlConnection sqlConnection, Action`1 act)
            at System.Data.SqlClient.SqlProviderServices.GetDbProviderManifestToken(DbConnection connection)
            at System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection)
   InnerException: 

更新

我做了一个简化的测试,以便更好地访问真正的底层错误,Bahri Gungor 是正确的,根本问题是未启用 MSDTC。

但是,由于我尝试在 Azure 项目中运行此代码,并且 Azure 不支持分布式事务,因此我不得不使用一种丑陋的解决方法。所有成员资格写入都必须在单独的事务中进行,这是非常不幸的。

感谢大家的帮助。

We are trying to integrate the System.Web.Providers membership management into a transaction using System.Transactions.TransactionScope and keep getting the following error message:

The operation is not valid for the state of the transaction.

Wrapped up in an exception with the following, more confusing message:

The provider did not return a ProviderManifestToken string.

Before anyone asks, yes we have verified that the connection string is correct and the user we're using to connect to the db has the proper permissions. If we take the attempt to call Membership.CreateUser() out of a TransactionScope block, it works. Put it in a TransactionScope and it fails.

There seems to be amazingly little information out there about the Universal Provider. Pretty much all you see are links to the NuGet page and Scott Hanselman's blog post from June.

Does anyone out there know how to get System.Web.Providers to participate in a transaction?

Thanks.

Here's the full stacktrace, in case it's helpful:

System.Data.ProviderIncompatibleException was unhandled by user code
  Message=The provider did not return a ProviderManifestToken string.
  Source=System.Data.Entity
  StackTrace:
       at System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection)
       at System.Web.Providers.Entities.ModelHelper.GetStorageMetadata(String providerName, DbConnection connection, String ssdl)
       at System.Web.Providers.Entities.ModelHelper.CreateMetadataWorkspace(String providerName, DbConnection connection, String csdl, String ssdl, String msl)
       at System.Web.Providers.Entities.ModelHelper.CreateEntityConnection(ConnectionStringSettings setting, String csdl, String ssdl, String msl)
       at System.Web.Providers.Entities.ModelHelper.CreateMembershipEntities(ConnectionStringSettings setting)
       at System.Web.Providers.DefaultMembershipProvider.Membership_CreateUser(String applicationName, String userName, String password, String salt, String email, String passwordQuestion, String passwordAnswer, Boolean isApproved, DateTime& createDate, Boolean uniqueEmail, Int32 passwordFormat, Object& providerUserKey)
       at System.Web.Providers.DefaultMembershipProvider.CreateUser(String username, String password, String email, String passwordQuestion, String passwordAnswer, Boolean isApproved, Object providerUserKey, MembershipCreateStatus& status)
       at System.Web.Security.Membership.CreateUser(String username, String password, String email, String passwordQuestion, String passwordAnswer, Boolean isApproved, Object providerUserKey, MembershipCreateStatus& status)
       at WcfLoginRegister.RegistrationService.RegisterUser(RegisterUserRequest request) in C:\Users\rmacgrogan\dev\pallas\parthenon\sandbox\FbEntityTypeTester\WcfLoginRegister\RegistrationService.svc.cs:line 43
       at SyncInvokeRegisterUser(Object , Object[] , Object[] )
       at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
       at     System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
  InnerException: System.Transactions.TransactionException
       Message=The operation is not valid for the state of the transaction.
       Source=System.Transactions
       StackTrace:
            at     System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction)
            at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
            at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
            at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
            at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
            at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
            at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
            at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
            at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
            at System.Data.SqlClient.SqlConnection.Open()
            at System.Data.SqlClient.SqlProviderServices.UsingConnection(SqlConnection sqlConnection, Action`1 act)
            at System.Data.SqlClient.SqlProviderServices.UsingMasterConnection(SqlConnection sqlConnection, Action`1 act)
            at System.Data.SqlClient.SqlProviderServices.GetDbProviderManifestToken(DbConnection connection)
            at System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection)
   InnerException: 

Update

I did a simplified test to get better access to the real underlying error, and Bahri Gungor is correct that the underlying issue is that MSDTC is not enabled.

However, since I am trying to run this code in an Azure project and since Azure does not support distributed transactions, I am stuck using an ugly workaround. All membership writes must occur in a separate transaction, which is pretty unfortunate.

Thanks everyone for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橘虞初梦 2024-12-18 13:29:05

我还没有尝试将 TransactionScope 与 ASPNet 会员服务一起使用,但是,任何将打开另一个事务(甚至是与数据库的第二个连接)的任何内容都将自动初始化 MSDTC 事务。如果机器上没有配置MSDTC(我假设是你的Web服务器),则交易无法成功创建。

在“管理工具”下,有一个名为“组件服务”的管理工具(控制面板 -> 系统和安全 -> 管理工具)。该工具打开后,您将在左侧看到组件服务。开放组件服务->计算机 ->我的电脑 ->分布式事务协调器->本地 DTC(右键单击并选择属性)。选择“安全”选项卡。

确保事务管理器通信同时选中“允许入站”和“允许出站”。还应检查网络 DTC 访问。我无法对其他设置进行更具体的说明,因为您的特定环境可能需要其他变量的不同设置。

我相信发生的情况是,您对 ASPNet 会员服务(具有其自己的 SQL Server 配置)的访问正在将事务提升为 MSDTC 事务,而某些设置(MSDTC 的安全性或配置)正在阻止其成功。通过简单的 Google 搜索,您就可以找到各种 MSDTC 故障排除文献(其中许多都在 Stack Overflow 上得到了解决)。但是,我会首先检查您的组件服务配置,并确保您可以执行分布式事务。

I haven't tried using TransactionScope with ASPNet Membership Services, however, anything that will open another transaction (even a second connection to the database) will automatically initialize an MSDTC transaction. If MSDTC is not configured on the machine (I assume your web server), the transaction cannot be created successfully.

Under Administrative Tools, there is a management tool called Component Services (Control Panel -> System and Security -> Administrative Tools). Once the tool opens, you will see Component Services on the left hand side. Open Component Services -> Computers -> My Computer -> Distributed Transaction Coordinator -> Local DTC (right click and select Properties). Select the Security Tab.

Make sure Transaction Manager Communication has both Allow Inbound and Allow Outbound checked. Network DTC access should also be checked. I can't be any more specific about the other settings because your specific environment might require different settings for the other variables.

I believe what is happening is that your access of the ASPNet Membership Services (which have its own SQL Server configuration) is promoting the transaction to a MSDTC transaction, and some setting (security or configuration of MSDTC) is preventing it from succeeding. You will find all sorts of MSDTC troubleshooting literature with a simple Google search (many of which are resolved on Stack Overflow). However, I would check your Component Services configuration first, and make sure you can execute a distributed transaction.

眼角的笑意。 2024-12-18 13:29:05

当您嵌套 TransactionScopes 时,可能会导致这种情况:

        using (var ts = new TransactionScope())
        {
            using(var tsInner1 = new TransactionScope())
            {
                //OOPS, I forgot to call Complete() or Rollback()
            }
            using (var tsInner2 = new TransactionScope())
            {
                //Any db action followed by a "Complete" will cause this error
                tsInner2.Complete();
            }
        }

但如果没有看到生成错误的代码,我无法确定。

This can be caused when you have nested TransactionScopes:

        using (var ts = new TransactionScope())
        {
            using(var tsInner1 = new TransactionScope())
            {
                //OOPS, I forgot to call Complete() or Rollback()
            }
            using (var tsInner2 = new TransactionScope())
            {
                //Any db action followed by a "Complete" will cause this error
                tsInner2.Complete();
            }
        }

But I cannot be sure without seeing the code that generated the error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文