c# - 在 TransactionScope 中登记 System.Web.Providers

标签 c# transactions asp.net-membership

我们正在尝试使用 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 block 中调用 Membership.CreateUser(),它会起作用。将它放在 TransactionScope 中,它会失败。

关于 Universal Provider 的信息似乎少得惊人。您看到的几乎都是 NuGet 页面的链接和 Scott Hanselman 6 月份的博客文章。

有没有人知道如何让 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 不支持分布式事务,因此我不得不使用一个丑陋的解决方法。所有成员写入必须发生在单独的事务中,这是非常不幸的。

感谢大家的帮助。

最佳答案

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

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

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

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

关于c# - 在 TransactionScope 中登记 System.Web.Providers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7881889/

相关文章:

c# - 在没有 Unity.MVC 的情况下解决 Unity 依赖关系

c# - Android(Xamarin) 如何通过蓝牙从手环获取数据(脉冲)

c# - 合并两个字符串(文本文件)

spring-mvc - Spring集成测试不回滚

java - 交易问题

c# - WebAPI : 'IHttpActionResult' does not contain a definition for 'GetAwaiter'

postgresql - 如果行已存在,Postgres 事务使用 UPDATE 而不是 INSERT

c# - 如何检查密码是否有效? ASP.NET MVC 成员资格

.net - ASP.net 成员资格 - 添加角色

c# - <MailDefinition> 和 <%%> 占位符