简体   繁体   English

add-migration命令在ApplicationDbContex上失败

[英]add-migration command fails on ApplicationDbContex

App : Asp.NET Core 1.1.1, EF Core App :Asp.NET Core 1.1.1,EF Core

Platform : Visual Studio 2017 5.3.3 平台 :Visual Studio 2017 5.3.3

Authentication Mode : Individual User Accounts 身份验证模式 :个人用户帐户

Following this tutorial from ASP.NET official team, the following command runs successfully: 遵循ASP.NET官方团队的本教程 ,以下命令将成功运行:

PM> Add-Migration MyFirstMigration -context BloggingContext

As we know VS2017 by default creates ApplicationDbContext under MyProject\\Data folder for creating user tables ( ASPNETUsers, ASPNETRoles etc... ) for authentication. 众所周知, VS2017默认情况下在MyProject \\ Data文件夹下创建ApplicationDbContext ,以创建用于身份验证的用户表( ASPNETUsers, ASPNETRoles etc... )。 But for that when I run the following command it first gives me Error-1 below. 但是为此,当我运行以下命令时,它首先给我下面的Error-1 And when I follow the instructions in first error message, I get Error-2 below. 当我按照第一条错误消息中的说明进行操作时,出现以下Error-2 Question : How do I make the following command work without using IDbContextFactory ? 问题 :如何在使用IDbContextFactory 情况下使以下命令起作用?

PM> Add-Migration MyFirstAuthenMigration -context ApplicationDbContext

Error 1 错误1

No parameterless constructor was found on 'ApplicationDbContext'. 在“ ApplicationDbContext”上找不到无参数的构造函数。 Either add a parameterless constructor to 'ApplicationDbContext' or add an implementation of 'IDbContextFactory' in the same assembly as 'ApplicationDbContext'. 在“ ApplicationDbContext”中添加无参数构造函数,或者在与“ ApplicationDbContext”相同的程序集中添加“ IDbContextFactory”的实现。

After I add a parameterless constructor in ApplicationDbContext.cs (shown below) I get the second error shown below: ApplicationDbContext.cs添加无参数构造函数(如下所示)后,出现第二个错误:

Error 2 错误2

No database provider has been configured for this DbContext. 没有为此DbContext配置数据库提供程序。 A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. 可以通过重写DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext来配置提供程序。 If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext. 如果使用AddDbContext,则还应确保DbContext类型在其构造函数中接受DbContextOptions对象,并将其传递给DbContext的基本构造函数。

ApplicationDbContext.cs ApplicationDbContext.cs

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    //NOTE: I added following constructor after Error 1 shown above
    public ApplicationDbContext()
    {
    }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        // Customize the ASP.NET Identity model and override the defaults if needed.
        // For example, you can rename the ASP.NET Identity table names and more.
        // Add your customizations after calling base.OnModelCreating(builder);
    }
}

You can't get it to work. 您无法使其正常工作。 Because EF needs to know which connectionstring should be used. 因为EF需要知道应该使用哪个连接字符串。 You can either put the connectionstring into your OnModelCreating method. 您可以将连接字符串放入OnModelCreating方法中。 Which is bad when you have more than one DB (dev, test and production for example). 当您有多个数据库(例如,开发,测试和生产)时,这很不好。 Or you implement IDbContextFactory which will be loaded by EF through reflection. 或者,您实现IDbContextFactory,该IDbContextFactory将由EF通过反射加载。

So implementing IDbContextFactory is the better option. 因此,实现IDbContextFactory是更好的选择。 Simply create it where you have your ApplicationDbContext. 只需在拥有ApplicationDbContext的位置创建它即可。 Sample implementation. 示例实施。

public class DomainContextFactory : IDbContextFactory<DomainContext>
{
    public string BasePath { get; protected set; }

    public DomainContext Create()
    {
        var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        var basePath = AppContext.BaseDirectory;
        return Create(basePath, environmentName);
    }

    public DomainContext Create(DbContextFactoryOptions options)
        => Create(options.ContentRootPath, options.EnvironmentName);

    private DomainContext Create(string basePath, string environmentName)
    {
        BasePath = basePath;
        var configuration = Configuration(basePath, environmentName);
        var connectionString = ConnectionString(configuration.Build());
        return Create(connectionString);
    }

    private DomainContext Create(string connectionString)
    {
        if (string.IsNullOrEmpty(connectionString))
        {
            throw new ArgumentException($"{nameof(connectionString)} is null or empty", nameof(connectionString));
        }
        var optionsBuilder = new DbContextOptionsBuilder<DomainContext>();
        return Configure(connectionString, optionsBuilder);
    }

    protected virtual IConfigurationBuilder Configuration(string basePath, string environmentName)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(basePath)
            .AddJsonFile("constr.json")
            .AddJsonFile($"constr.{environmentName}.json", true)
            .AddEnvironmentVariables();
        return builder;
    }

    protected virtual string ConnectionString(IConfigurationRoot configuration)
    {
        string connectionString = configuration["ConnectionStrings:DefaultConnection"];
        return connectionString;
    }

    protected virtual DomainContext Configure(string connectionString, DbContextOptionsBuilder<DomainContext> builder)
    {
        builder.UseSqlServer(connectionString, opt => opt.UseRowNumberForPaging());
        DomainContext db = new DomainContext(builder.Options);
        return db;
    }

    DomainContext IDbContextFactory<DomainContext>.Create(DbContextFactoryOptions options)
        => Create(options.ContentRootPath, options.EnvironmentName);
}

It works with 3 configuration files (final, local and test) 它可以使用3个配置文件(最终,本地和测试)

  • constr.dev-final.json constr.dev-final.json
  • constr.dev-local.json constr.dev-local.json
  • constr.dev-test.json constr.dev-test.json

The usage looks like the following: 用法如下所示:

public override IServiceResult<IList<Rolle>> LoadAllData()
{
    using (var db = this.DomainContextFactory.Create())
    {
        Task<List<Rolle>> rollen = db.Roles
            .ToListAsync<Rolle>();
        return new ServiceResult<IList<Rolle>>(rollen.Result, rollen.Result.Count);

    }
}

And using "Add-Migration" inside MSVC works also. 并且在MSVC中使用“添加迁移”也可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM