16

In one of my IDatabaseInitializer in Seed method given my DbContext I insert initial data to DB. Among other things there are some users to be initialized. But as far as I use Microsoft.AspNet.Identity.EntityFramework.UserStore with Microsoft.AspNet.Identity.UserManager which has only asynchronous methods it makes DbUpdateConcurrencyException as follows:

private static void CreateUser(DbContext context, string[] roles, string userName, string userEmail) {

    // given context is 
    var user = new ApplicationUser { /* ... fields init */  };

    var userStoreAdapter = new ApplicationUserRepository(context);
    var manager = new UserManager<ApplicationUser>(userStoreAdapter);

    // pass the creation to manager by calling it synchronously. See UserManagerExtensions
    manager.Create(user, Domain.Constants.DefaultPassword);
    manager.AddToRoles(user.Id, roles);

    context.SaveChanges(); // throws DbUpdateConcurrencyException. See another approach below.
}

So the question is if there is a way to use UserManager with DbContext without concurrency issues?

I've tried the following approach taken from Optimistic Concurrency Patterns but that does not create users:

bool isSaved = true;
do
{
    try
    {
        context.SaveChanges();
        isSaved = true;
    }
    catch (DbUpdateConcurrencyException ex)
    {
        foreach (var entry in ex.Entries)
        {
            entry.Reload();
        }
        isSaved = false;
    }
} while (!isSaved);
Artyom
  • 3,507
  • 2
  • 34
  • 67
  • I think your question breaks down to, "how do I call an async method from a sync method?" If so, this may help you: http://stackoverflow.com/questions/22628087/calling-async-method-synchronously – Nathan A Sep 29 '15 at 15:02
  • 1
    @NathanA `Task` always runs in another thread, right? So `UserManager` updates DB while the given `DbContext` is not aware of it. And it breaks with the concurrency exception as above. So could I run it in the current thread? The post does not look to help. [`AsyncHelper`](https://aspnetidentity.codeplex.com/SourceControl/latest#src/Microsoft.AspNet.Identity.Core/AsyncHelper.cs) which is called by the extension methods for `UserManager` does the similar thing. – Artyom Sep 29 '15 at 15:53
  • I believe I have the same issue. In my situation the client kicks off a lengthy database script and the server's response is a 200 OK. But after the lengthy process completes I attempt to run the _RoleManager.CreateAsync and nothing happens. Did you find a work around? @Artyom? – T3.0 Oct 21 '19 at 05:11
  • 1
    Does this answer your question? [How would I run an async Task method synchronously?](https://stackoverflow.com/questions/5095183/how-would-i-run-an-async-taskt-method-synchronously) – Clint May 24 '21 at 14:13

2 Answers2

2
var result = Task.Run(() => {
   /*whatever you want here*/
}).Result;

// Do whatever u want with the result after
Massaynus
  • 322
  • 2
  • 9
-1

To use the UserManager synchronously you need to call the .GetAwaiter().GetResult() extension methods from System.Threading.Tasks. For example to get the current user synchronously using the user manager:

using System.Threading.Tasks;
var currentUser = _userManager.GetUserAsync(User).GetAwaiter().GetResult();

These two extension methods from the System.Threading.Tasks namespace gets the awaiter for the task GetUsersAsync() and gets the result.

11738472
  • 184
  • 3
  • 22
  • `async` keyword doesn't make your code running in parallel. All it does is relieves the thread while waiting for I/O operation to complete. So it is not the case here – OlegI Sep 10 '20 at 07:38
  • 1
    If you check the CreateUser method above it is a synchronous method, and the user wants to use UserManager in a synchronous method not to run the code parallel if that is the case they did not mention it in the question – Phathutshedzo Khabubu Sep 10 '20 at 07:46
  • There are no async method calls in OP's code. They don't describe their problem correctly. – Gert Arnold Sep 10 '20 at 09:56
  • It worked for me to convert User object, thence the upvote – Tom Chadaravicius Oct 28 '20 at 22:06
  • GetAwaiter().GetResult() didn't work for me. Also _userManager.GetUserAsync(User).Result didn't work for me. – Meeting Attender Apr 06 '21 at 20:35