2015-09-30 3 views
7

я делаю регистрацию, на которой я прошу 5 вещей:Как создать транзакцию с идентификатором asp.net?

ПолноеИмя, EMAILID, пароль, ContactNumber, Пол

Теперь EMAILID и пароль я храню с регистровым методом и приведено в ниже два ссылки :

public async Task<ActionResult> Register(RegisterViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; 

      using var context = new MyEntities()) 
      { 
       using (var transaction = context.Database.BeginTransaction()) 
       { 
        try 
        { 
         var DataModel = new UserMaster(); 
         DataModel.Gender = model.Gender.ToString(); 
         DataModel.Name = string.Empty; 
         var result = await UserManager.CreateAsync(user, model.Password);//Doing entry in AspnetUser even if transaction fails 
         if (result.Succeeded) 
         { 
          await this.UserManager.AddToRoleAsync(user.Id, model.Role.ToString()); 
          this.AddUser(DataModel, context); 
          transaction.Commit(); 
          return View("DisplayEmail"); 
         } 
         AddErrors(result); 
        } 
        catch (Exception ex) 
        { 
         transaction.Rollback(); 
         return null; 
        } 

       } 
      } 
     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 

public int AddUser(UserMaster _addUser, MyEntities _context) 
    { 
     _context.UserMaster.Add(_addUser);   
     _context.SaveChanges(); 
     return 0; 
    } 

Теперь с этим ниже 2 линии:

var result = await UserManager.CreateAsync(user, model.Password);//entry is done in AspnetUsers table. 
await this.UserManager.AddToRoleAsync(user.Id, model.Role.ToString());//entry is done is Aspnetuserrole table 

Теперь это полное имя, контактно, пол, который у меня есть в другой таблице, которая составляет UserMaster.

Так что, когда я представит свою регистрационную форму спасу это детали в UserMaster и AspnetUsers, AspnetUserinrole стол.

Но подумайте, есть ли какие-либо проблемы при сохранении записи в UserMaster, тогда я не хочу сохранять запись в Aspnetuser и Aspnetuserinrole.

Я хотел бы создать транзакцию, в которой я буду откатываться, если возникнет какая-либо проблема при сохранении любой записи в любой таблице. I. В AspnetUser, AspnetUserinRole nd userMaster не должно быть записи.

Записи должны быть успешно сохранены, только если нет проблем с сохранением записи в этих трех таблицах, иначе транзакция должна быть возвращена.

Я использую Microsoft.AspNet.Identity для входа в систему, регистр, управление ролями и другие и после этого урока:

http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-web-app-with-email-confirmation-and-password-reset

http://www.asp.net/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity

Но, как ожидают UserManager.CreateAsync и UserManager .AddToRoleAsync метод встроен в метод, как бы синхронизировать его для работы с сущностью.

Так может ли кто-нибудь вести меня, как создать такую ​​транзакцию или что-нибудь, что разрешило бы это?

IdentityConfig:

public class ApplicationUserManager : UserManager<ApplicationUser> 
    { 
     public ApplicationUserManager(IUserStore<ApplicationUser> store) 
      : base(store) 
     { 
     } 

     public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
     { 
      var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>())); 
      // Configure validation logic for usernames 
      manager.UserValidator = new UserValidator<ApplicationUser>(manager) 
      { 
       AllowOnlyAlphanumericUserNames = false, 
       RequireUniqueEmail = true 
      }; 

      // Configure validation logic for passwords 
      manager.PasswordValidator = new PasswordValidator 
      { 
       RequiredLength = 6, 
       RequireNonLetterOrDigit = true, 
       RequireDigit = true, 
       RequireLowercase = true, 
       RequireUppercase = true, 
      }; 

      // Configure user lockout defaults 
      manager.UserLockoutEnabledByDefault = true; 
      manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); 
      manager.MaxFailedAccessAttemptsBeforeLockout = 5; 

      // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user 
      // You can write your own provider and plug it in here. 
      manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser> 
      { 
       MessageFormat = "Your security code is {0}" 
      }); 
      manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser> 
      { 
       Subject = "Security Code", 
       BodyFormat = "Your security code is {0}" 
      }); 
      manager.EmailService = new EmailService(); 
      manager.SmsService = new SmsService(); 
      var dataProtectionProvider = options.DataProtectionProvider; 
      if (dataProtectionProvider != null) 
      { 
       manager.UserTokenProvider = 
        new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity")); 
      } 
      return manager; 
     } 
    } 

    // Configure the application sign-in manager which is used in this application. 
    public class ApplicationSignInManager : SignInManager<ApplicationUser, string> 
    { 
     public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) 
      : base(userManager, authenticationManager) 
     { 
     } 

     public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user) 
     { 
      return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); 
     } 

     public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context) 
     { 
      return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication); 
     } 
    } 

ответ

6

Вы не должны создавать новый контекст дб, но использовать существующий

var context = Request.GetOwinContext().Get<MyEntities>() 

Он создается для каждого запроса, если вы используете реализацию по умолчанию

app.CreatePerOwinContext(ApplicationDbContext.Create); 

Update:

ОК, так как вы используете два разных контекста, ваш код будет выглядеть примерно так:

public async Task<ActionResult> Register(RegisterViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; 

      var appDbContext = HttpContext.GetOwinContext().Get<ApplicationDbContext>(); 
      using(var context = new MyEntities()) 
      using (var transaction = appDbContext.Database.BeginTransaction()) 
       { 
        try 
        { 
         var DataModel = new UserMaster(); 
         DataModel.Gender = model.Gender.ToString(); 
         DataModel.Name = string.Empty; 
         var result = await UserManager.CreateAsync(user, model.Password);//Doing entry in AspnetUser even if transaction fails 
         if (result.Succeeded) 
         { 
          await this.UserManager.AddToRoleAsync(user.Id, model.Role.ToString()); 
          this.AddUser(DataModel, context); 
          transaction.Commit(); 
          return View("DisplayEmail"); 
         } 
         AddErrors(result); 
        } 
        catch (Exception ex) 
        { 
         transaction.Rollback(); 
         return null; 
        } 

       } 
     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 

    public int AddUser(UserMaster _addUser, MyEntities _context) 
    { 
     _context.UserMaster.Add(_addUser); 
     _context.SaveChanges(); 
     return 0; 
    } 

здесь appDbContext тот же контекст, который используется UserManager

+0

Можете ли вы, пожалуйста, расширить свои анны и попытаться поместить это в мой код, потому что это первый раз, когда я использую этот owin и mircosoft identity.so его запрос, который вы, пожалуйста, предоставьте несколько подробностей. –

+0

Его собственный шаблон mvc, но код, который я использую из этой ссылки только 2, которую я предоставил в своем вопросе –

+0

См. Мой обновленный код, и я использую подход базы данных First entity –

2

Вы можете решить с TransactionScope класса:

using (TransactionScope scope = new TransactionScope()) 
{ 
    var result = await UserManager.CreateAsync(user, model.Password); 
    if (result.Succeeded) 
    { 
     await this.UserManager.AddToRoleAsync(user.Id, model.Role.ToString()); 
     string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id, "Confirm your account"); 
     return View("DisplayEmail"); 
    } 
    scope.Complete(); 
} 

Таким образом, оба действия будут сделаны в одной транзакции, и если метод Comlete не вызывает, как действия будет отменен (roolback).

Если вы хотите решить проблему только с помощью EF (без TransactionScope), вам необходимо реорганизовать свой код. Я не знаю, как реализовать класс UserManager и методы CreateAsync и AddToRoleAsync, но я предполагаю, что они создают новый DBC-текст для каждой операции. Итак, во-первых, для всех транзакционных операций вам нужен один DBContext (для решения EF).Если вы добавите эти методы, я изменю свой ответ в соответствии с решением EF.

+0

Пожалуйста, смотрите мой обновленный вопрос с обновленным кодом, но по-прежнему создается запись в AspnetUser, хотя сделка не удается, потому что CreateAsync и AddToRoleAsync не имеют ничего общего с рамкой сущности еще я не так уверен в этом. –

+1

@ Загружает 'UserManager' принимает' UserStore', а 'DbContext' - зависимость конструктора в последнем. Таким образом, Identity не создает для вас контекста - это уже один контекст. – trailmax

+0

Использование области транзакций для меня не срабатывало ... 'UserManager.CreateAsync' время от времени каждый раз – JobaDiniz