4

I have a complex add process for creating a user(and adds roles + other user related information to other tables)

Does anyone know how to use Transactions when adding a user/role or other Identity objects. I cannot seem to access "Database.BeginTransaction"

I have the following UserManager class, i am not sure how i can access the base class "store"

public class UserManager : UserManager<ApplicationUser>
{
    public UserManager()
    : base(new UserStore<ApplicationUser>(new ApplicationDbContext()))
    {
        //allows alphanumeric names in username
        UserValidator = new UserValidator<ApplicationUser>(this) { AllowOnlyAlphanumericUserNames = false };
    }

}

There doesnt seem to be a means to access UserManager.UserStore.Database...

Thanks

Piotr Stulinski
  • 9,241
  • 8
  • 31
  • 46

1 Answers1

4

ASP.NET Identity framework's current storage implementation uses EntityFramework. DbContext is the heart of EF where TransactionScope can be used to save multiple changes.

Below is an example from EF Code First DBContext and Transactions

using(var scope = new TransactionScope(TransactionScopeOption.Required,
    new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
{
    // Do something like Add a User 
    context.SaveChanges();
    // Do something like Add a User to Role
    context.SaveChanges();

    scope.Complete();
}

UPDATE 1: - To access the DbContext.Database use IdentityManager.Store.Context.Database - You can use the same approach across multiple DbContext using same ConnectionString (not SqlConnection object)

Moreover, look into next link for usage of BeginTransaction. -> How do you configure the Transaction time out in Entity Framework 6 DbContext.Database.BeginTransaction?

Update 2:

Using the EF6 BeginTransaction : Working with Transactions (EF6 Onwards)

Use following a code pseudo

ApplicationDbContext ctx = new ApplicationDbContext();
using (DbContextTransaction tran1 = ctx.Database.BeginTransaction())
{
    using (MyDbContext ctx2 = new MyDbContext(ctx.Database.Connection, false))
    {
        ctx2.Database.UseTransaction(tran1.UnderlyingTransaction);
    }
}

from the Working with Transactions (EF6 Onwards)

Note: The contextOwnsConnection flag must be set to false when called in this scenario. This is important as it informs Entity Framework that it should not close the connection when it is done with it

Community
  • 1
  • 1
jd4u
  • 5,789
  • 2
  • 28
  • 28
  • Sorry, my problem is that i am trying to do this across two contexts hence i need to use the new features in EntityFramework 6 and "BeginTransaction" -- as far as i know. – Piotr Stulinski Oct 29 '13 at 16:48
  • You can use the same approach across multiple DbContext using same ConnectionString (not SqlConnection object). – jd4u Oct 29 '13 at 17:02
  • In UserManager constructor, instead of passing direct instance to base, keep reference of Store and Context and make it available to your application as required. – jd4u Oct 30 '13 at 06:58
  • I will mark that as correct. i guess it would have been nice if they had left access to this in the base UserManager – Piotr Stulinski Oct 30 '13 at 09:36