1
votes

I have the following class derived from entity framework class as follows.

internal class MyInitializer : CreateDatabaseIfNotExists<ConfigurationDbContext>
{
    protected override async void Seed(ConfigurationDbContext context)
    {
        await DbHelper.AddSampleDataAsync(context);
        base.Seed(context);
    }
}

I get the following compiler error when I change "void" to "async Task".

return type must be 'void' to match overridden member

async/await best practices tell you to almost always return async Task instead of void. Just wanted to make sure my usage of void here is one of those acceptable scenarios for using void. What other options do I have anyways?

2
Your overriding a method, thus you have to have the same signature of the method as the overridden one. - Håkan Fahlstedt
Will the type function properly if you do the work asynchronously and anyone calling Seed (either through this type or through the parent type) going to function properly if it returns before the work is actually done, and without providing any means of determining the result (or any errors) of this operation? If yes, leave the async void method, if no, you have to either not do the operation asynchronously, or not meet this signature. - Servy
EF expects this to happen synchronously, so you should add your seed data synchronously. - Charles Mager
@CharlesMager, I think you are right. I also think EF should provide SeedAsync(). - SamDevx
@Servy, since EF does not provide SeedAsync(), JNYRanger's solution seems pretty good, don't you think? - SamDevx

2 Answers

2
votes

In C#, overridden members must have exactly the same signature as the method they are overriding. You simple can't override a method with another method of a different return type.

Because the base class expect the method to run syncronously, you would have to wait for the async method to complete before returning.

internal class MyInitializer : CreateDatabaseIfNotExists<ConfigurationDbContext>
{
    protected override void Seed(ConfigurationDbContext context)
    {
        DbHelper.AddSampleDataAsync(context).Wait();
        base.Seed(context);
    }
}
2
votes

When overriding a method it must have the same signature as the original method of the base class (or an interface / abstract class). I would imagine based on this question the expected behavior of Seed() is a synchronous operation. Therefore it's not a good idea to override it and completely change the behavior to asynchronous.

Instead you should create a second method that is asynchronous, and keep the synchronous one.

This method below (as suggested by @DanielEarwicker) allows you to have BOTH a synchronous and asynchronous version by waiting for the asynchronous operation to complete in the synchronous version of Seed()

internal class MyInitializer : CreateDatabaseIfNotExists<ConfigurationDbContext>
{
    protected override void Seed(ConfigurationDbContext context)
    {
        SeedAsync(context).Wait();
    }

    protected async Task SeedAsync(ConfigurationDbContext context)
    {
        await DbHelper.AddSampleDataAsync(context);
        base.Seed(context)
    }
}