0

asp.net 멤버쉽을 MVC4의 새 단순 멤버 공급자로 업그레이드하는 중입니다. 이것은 Azure/Sql Azure 앱으로 localhost에서는 제대로 실행되지만 배포시 실패합니다. 내가 역할 클래스를 채울 this technique을 사용하고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) 
       } 
      } 

다음과 같이 나는 트랜잭션에 코드가 있습니다. 스택 추적은 실제로 해당 호출을 완료하기 위해 하위 트랜잭션을 실행하려고 시도하고 있음을 나타냅니다. simplemembership 테이블은 다른 db에 있습니다. 별도의 트랜잭션 컨텍스트 내에서 역할 공급자로부터 역할 정보를 검색하려면 어떻게해야합니까?

답변

0

문제는 GetRolesForUser은 두 번째 데이터베이스에 대한 새 연결을 열어서 차례대로 TransactionScope에 있음을 나타냅니다. 그런 다음이 (MSDN - System.Transactions Integration with SQL Server)은 DTC로 승격됩니다. 당신은 몇 가지 옵션을 시도 할 수 :

얻을 거래 전에 역할은

을 시작 당신은 밖에서 TransactionScopestring[] roles를 검색 할 수 있습니다. 범위 안에 넣어야 할 이유가 있습니까? 을 감안할 때 당신은 말할 것이 : 당신이 TransactionScope 전에 롤 정보를 얻을 아무런 문제가 없었다처럼

는 소리

가 어떻게 별도의 트랜잭션의 컨텍스트 내에서 역할 공급자에서 역할 정보를 검색 할 수 있습니다 .

은 "입대 = 거짓"(SqlConnection.ConnectionString 참조) 연결 문자열에, 그래서이 힘을 넣어

당신은 거래에 참여하지 않는 연결 문자열을 말할 수있는 간단한 회원 연결 문자열에 거래를 끄고 단순 회원으로 사용하는 데이터베이스에 대한 거래가 필요없는 경우 귀하를위한 하나의 옵션이 될 것입니다. 그것을 만들어 SimpleRoleProvider를 들어 트랜잭션

전에 간단한 회원의 연결을 여는

봅니다 데이터베이스 객체의 다음 그것을 그것을 사용하는 처음을 엽니 다. 그러나, 그것은 닫을 때까지 그것을 닫지 않습니다 ... . GetRolesForUser을 호출 할 때마다 연결이 열리므로 운이 없네요. TransactionScope이 열리기 전에 GetRolesForUser을 한 번 호출 한 다음 이미 열려있는 연결을 사용하여 범위 내부에서 다시 호출 할 수 있다고 생각했습니다. IObjectContextAdapter

면책 조항

재생 : 나는 당신의 설치를 테스트 할 수있는이 작업을 약속 할 수 없다.

트랜잭션 범위 외부의 비 트랜잭션 연결 문자열을 먼저 열어 트릭을 실행하여 두 연결 문자열로 프로모션을 방지하면 트랜잭션을 올리지 않아야합니다.Close에 동일한 연결을 설정 한 다음 Open을 동일한 트랜잭션 범위 (프로모션을 유발할 수 있음)에 넣는 경우에도이 방법을 사용할 수 있습니다.

컨텍스트에서이 작업을 시도해 볼 수 있습니다. 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