0

我正在将asp.net成员资格升级为MVC4中新的简单成员提供程序。这是一个Azure/Sql Azure应用程序,它可以在本地主机上正常运行,但在部署时会失败。我有代码的交易如下:Simplerole提供程序导致事务处理范围内的远程事务

  TransactionOptions toptions = new TransactionOptions(); 
      toptions.IsolationLevel = System.Transactions.IsolationLevel.Serializable; 
      using (TransactionScope trans = new TransactionScope(TransactionScopeOption.Required, toptions)) 
      { 
       try 
       { 
        ... do a bunch of database stuff in a single dbContext ... 

        var roleprov = (SimpleRoleProvider)Roles.Provider; 
        string[] roles = roleprov.GetRolesForUser(Username); 
        // above line fails with The transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D024) 
       } 
      } 

我使用this technique填充角色类。堆栈跟踪似乎表明它确实试图启动一个子事务来完成该调用。 simplemembership表在不同的数据库中。如何从单独事务的上下文中的角色提供者获取角色信息?

回答

0

问题是GetRolesForUser会导致新的连接打开到第二个数据库,然后又会得到它在TransactionScope中。反过来这(MSDN - System.Transactions Integration with SQL Server)然后促进到DTC。你可以尝试以下几种选择:

获取交易之前角色开始

你可以检索string[] rolesTransactionScope。你是否有理由让它们进入范围?既然你说:

我如何可以检索从一个单独的事务的上下文中的角色提供角色信息

这听起来像你能拿TransactionScope之前的角色信息,并没有任何问题。

关闭交易了简单的会员连接字符串

你可以告诉一个连接字符串不参与交易通过将“争取=假”(见SqlConnection.ConnectionString)在连接字符串中,所以这可能如果您从不需要使用简单成员资格数据库的事务处理,那么您可以选择一个选项。

尝试打开该交易

之前简单会员连接对于 SimpleRoleProvider它创建它的数据库对象,然后打开它,它使用它的第一次。但是,它不会在...... 之前关闭它。 从头开始,每次打到GetRolesForUser时都会打开连接,所以你运气不好。我想你可以在TransactionScope打开之前调用GetRolesForUser一次,然后再次使用已经打开的连接在范围内 - 你不能。

播放与IObjectContextAdapter

免责声明:我不能保证这会工作,我不能与你的设置进行测试。

您可以使用技巧来阻止使用两个连接字符串进行提升,方法是先在事务范围外打开非事务连接字符串,然后不应提升事务。如果您在同一个事务处理范围内(否则会导致升级)导致与CloseOpen的连接相同,也可以使用此功能。

您可以尝试与您的上下文,并查看是否停止GetRolesForUser促进交易,但我怀疑这将工作,因为GetRolesForUser导致连接打开,如果它尚未。由于我无法在您的场景中进行测试,因此我会将其纳入以防万一。

using (var db = new ExampleContext()) 
{ 
    var adapter = db as System.Data.Entity.Infrastructure.IObjectContextAdapter; 
    using (var conn = adapter.ObjectContext.Connection) 
    { 
     conn.Open(); 
     using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required)) 
     { 
      // perform operations 
      db.SaveChanges(); 
      // perform more operations 
      db.SaveChanges(); 
      // perform even more operations 
      db.SaveChanges(); 

      // If you don't complete, the transaction won't commit and you will lose the changes 
      scope.Complete(); 
     } 
    } 
} 
+0

最后,我找到了一种方法将角色从事务处理中取出。这有点尴尬,但它工作。我在这里发现了一篇关于该问题的文章(http://social.technet.microsoft.com/wiki/contents/articles/handling-transactions-in-sql-azure.aspx) – AldenG

+0

@AldenG。是的,所以(“_当你有多个连接到不同的数据库._)证实了我上面所说的。最后是否使用'SqlTransaction'而不是?我留下了该选项,因为我认为你需要坚持使用Roles和DbContext以减少与数据库的耦合 –

+0

我使用SqlTransaction玩了一个小时,并找不到一种方式使它与实体框架很好地协作,将它从事务处理器中拉出来最终获得了最简单的解决方案,并且使用了一对扩展方法要访问角色,代码结束了足够干净。感谢您的帮助。 – AldenG

相关问题