TransactionScope с вызовами членства и ролей в одном блоке (способ использовать только одно соединение?)

#c# #membership #roles #transactionscope

#c# #членство #роли #transactionscope

Вопрос:

У меня есть вызовы API членства и API ролей в одной и той же области транзакции. Я читал, что открытие более одного соединения приводит к эскалации, требующей включения распределенных транзакций, поэтому я ищу способ открыть одно соединение и поделиться им с: Членство, роли, мои собственные вызовы.

Вот рабочий код, который вызывает нежелательную эскалацию:

 public static void InsertUser(string userName, string email, string roleName, int contactId, string comment)
      {
         /*
          * Exceptions thrown here are caught in the DetailView's event handler and piped to the UI.
          */

         using(var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
         {
            string password = Membership.GeneratePassword(Membership.MinRequiredPasswordLength, Membership.MinRequiredNonAlphanumericCharacters);
            const string passwordQuestion = "Should you change your password question?";
            const string passwordAnswer = "yes";
            MembershipCreateStatus status;
            MembershipUser user = Membership.CreateUser(userName, password, email, passwordQuestion, passwordAnswer, true, out status);

            if(user == null)
            {
               throw new Exception(GetErrorMessage(status));
            }

            // Flesh out new user
            user.Comment = comment;
            Membership.UpdateUser(user);

            // Give user a role
            Roles.AddUserToRole(user.UserName, roleName);

            // Create bridge table record
            Guid userId = (Guid)ExceptionUtils.ThrowIfDefaultValue(user.ProviderUserKey, "ProviderUserkey is null!");
            insertIntoAspnet_Users_To_Contact(userId, contactId);

            // Send welcome email
            EmailUtils.SendWelcomeEmailFromAdmin(userName, email, password, passwordQuestion, passwordAnswer, roleName);

            transactionScope.Complete();
         }
      }
  

Спасибо

Комментарии:

1. установлены ли ваши подключения к базе данных в пул? если это так, базовое соединение останется открытым в течение нескольких секунд, чтобы посмотреть, будете ли вы отправлять дополнительные запросы. Если это так, он просто использует то же соединение, даже если вы используете новый объект connection. я полагаю, что все сводится к объединению в пул соединений.

Ответ №1:

Если у вас SQL2008 или выше, он может обрабатывать транзакцию через несколько подключений без перехода на MSDTC. Требование заключается в том, чтобы вы использовали точно такую же строку подключения для всех подключений.

Если вы используете более низкую версию SQL Server, я думаю, что вы проиграли. Я исследовал это несколько месяцев назад и не нашел способа справиться с этим, поэтому в итоге я пропустил транзакции и вместо этого внедрил собственную обработку ошибок. У клиента был SQL2005, и обновление было невозможно.

Ответ №2:

Вы указали TransactionScopeOption.RequiresNew , что означает, что вы хотите выполнять новую транзакцию каждый раз, когда вы передаете этот фрагмент кода, даже если уже существует подходящая внешняя транзакция.

Просто сделайте это:

 using(var transactionScope = new TransactionScope())
  

Комментарии:

1. Из того, что я прочитал, наличие нескольких открытых соединений вызывает эскалацию, которая требует включения MSDTC. В любом случае, использование пустого конструктора, к сожалению, не решило эту проблему.