3

I am coding a MVC 5 internet application and would like to know how to call an async method from the seed method when a database is created.

Here is my code:

public class ApplicationDbInitializer : CreateDatabaseIfNotExists<ApplicationDbContext> 
{
    protected override void Seed(ApplicationDbContext context) {            
        SetupAdminAndSampleObjectsDatabase();
        base.Seed(context);
    }
}

Currently, when calling the SetupAdminAndSampleObjectsDatabase method, I am getting the following error:

System.NotSupportedException: A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.

Here is the method definition:

public async Task SetupAdminAndSampleObjectsDatabase()

I am adding multiple objects in this method.

Am I correct in saying that the above error will be resolved if the SetupAdminAndSampleObjectsDatabase method is called with the await keyword?

So, in summary, how can I call an async method from the database seed method? Is this possible?

Thanks in advance.

Simon
  • 7,991
  • 21
  • 83
  • 163

1 Answers1

2

You can do one of two things:

1) Make the Seed method async, and use await

protected override async void Seed(ApplicationDbContext context) {            
        await SetupAdminAndSampleObjectsDatabase();
        base.Seed(context);
    }

2) Use .WaitAndUnwrapException() on the async method

protected override void Seed(ApplicationDbContext context) {            
        SetupAdminAndSampleObjectsDatabase().WaitAndUnwrapException();
        base.Seed(context);
    }

Hope that helps!

codechinchilla
  • 2,129
  • 13
  • 23
  • Thank you. I was not aware that I could add the async keyword to the override method. – Simon May 18 '15 at 04:04
  • Just a side note, if you use option 1, you will need to change the return type of `SetupAdminAndSampleObjectsDatabase()` to `Task` if it was originally `void` or `Task` for whatever the original return type `T` was in order to be able to await it. – akousmata Aug 07 '15 at 02:11
  • 1
    I wouldn't be too optimistic that I can get away with option 1. In that case, the caller would not await the created Task and you might end up with an error similar to this: "An asynchronous module or handler completed while an asynchronous operation was still pending". MSDN sates that async void is only possible "to make asynchronous event handlers possible". – Paul Jan 23 '17 at 22:12