How to Add an implementation of 'IDesignTimeDbContextFactory<DataContext>' to the project in asp.net-core-2.0

南楼画角 提交于 2019-12-03 05:41:45

EDIT: now obsolete. Microsoft updated their migration document at the end of September to show how to update so you do not need this workaround.

As seen on this issue I raised on github, you move your DB initialisation code to the Program main, putting it in between BuildWebHost() and .Run()

Its relatively easy once you understand you need to get the DB context using var context = services.GetRequiredService<MyContext>(); in Main and then everything works as expected. (though I still think DB initialisation is a one-time initialisation thing, not an every-program-run thing)

Simply changed my Program.cs

from this

public class Program
{
  public static void Main(string[] args)
  {
    var host = new WebHostBuilder()
      .UseKestrel()
      .UseContentRoot(Directory.GetCurrentDirectory())
      .UseIISIntegration()
      .UseStartup<Startup>()
      .Build();

    host.Run();
  }
}

to this

public class Program
{
  public static void Main(string[] args)
  {
    BuildWebHost(args).Run();
  }

  public static IWebHost BuildWebHost(string[] args) =>
      WebHost.CreateDefaultBuilder(args)
          .UseStartup<Startup>()
          .Build();
}

Source: https://wildermuth.com/2017/07/06/Program-cs-in-ASP-NET-Core-2-0

In 2.0 projects, move the SeedData.Initialize call to the Main method of Program.cs:

var host = BuildWebHost(args);

using (var scope = host.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    try
    {
        SeedData.Initialize(services, "").Wait();
    }
    catch (Exception ex)
    {
        var logger = services.GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "An error occurred seeding the DB.");
    }
}

host.Run();   

Reference: https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/#move-database-initialization-code

I had the same issue on latest .Net Core 2.0.3. I have separate project with dbContext implementation (from my custom interface IUnitOfWork), and at first - migration was worked perfectly. But after I have implemented some other infrastructure - I have got the similar error:

Unable to create an object of type 'TestCoreUnitOfWork'. Add an implementation of 'IDesignTimeDbContextFactory' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.

The suggested solution about implementation IDesignTimeDbContextFactory is fine, but I was wondering why migrations have worked before? I have spent few hours, to find out, which code change was break the migration. And as it turned out, it was initialization of bootstrappers, where I have load all referenced assemblies (via Assembly.Load()) from my solution. After I have changed this to more traditional way with direct call of all bootstrappers - migration began to work again.

To sum up and answering for the question, the one is possible reason of the migration error - using Assembly.Load() in the StartUp.ConfigureServices().

I hope it will be useful to someone.

For me I made the my DBContext class with Constructor Injection and it give this error. I reverted back to have parameterless constructor than it work.

The problem is with seeding db from Startup.Configure... you can still do it with this work around. Tested and worked fine

https://garywoodfine.com/how-to-seed-your-ef-core-database/

It look like EF 2.0 don't work with "sample data" which remains from the old net core template of the project. I managed to get rid of this error just commenting the next line:

SampleData.Initialize(app.ApplicationServices);

I think

var context = serviceProvider.GetService<ApplicationDbContext>();
context.Database.Migrate();

cases this error. I'm not sure whether this fix is correct but it works.

This is related to the new init process of .NET Core 2.0, in which the configuration is handled differently (details here).

If you upgraded from 1.x, modify your Program.cs and Startup.cs:

public class Program
{
    public static void Main(String[] args)
    {
        Program.BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(String[] args) =>
        WebHost.CreateDefaultBuilder(args)
               .UseKestrel()
               .UseUrls("http://*:8000")
               .UseStartup<Startup>()
               .Build();
}

public class Statup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    ........
}

After this modification your migrations should work and there is no need for an implementation of IDesignTimeDbContextFactory.

I came across with this error while using Npgsql.EntityFrameworkCore.PostgreSQL, if it matters.

Taking in account https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/#add-configuration-providers

I added this to BuildWebHost()

.ConfigureAppConfiguration((hostContext, config) =>
{
    // delete all default configuration providers
    config.Sources.Clear();
    config.AddJsonFile("appsettings.json", optional: true);
})

so it bacame:

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureAppConfiguration((hostContext, config) =>
    {
        // delete all default configuration providers
        config.Sources.Clear();
        config.AddJsonFile("appsettings.json", optional: true);
    })
    .Build();

Now it works

Some people said that you have to change your Startup.cs class, but I din't do nothing of that, just changed a little my Program.cs class

----------Old file--------------

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<MvcMovieContext>();
                context.Database.Migrate();
                SeedData.Initialize(services);
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred seeding the DB.");
            }
        }

        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

----------New File---------

public static void Main(string[] args)
    {
        var host = BuildWebHost(args);

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            try
            {
                var dbContext = scope.ServiceProvider.GetService<MvcMovieContext>();
                //SeeData is a class in my Models folder
                SeedData.Initialize(services);
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred seeding the DB.");
            }
        }
        host.Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .Build();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!