ApplicationDbContex上的add-migration命令失败

时间:2017-09-04 03:57:08

标签: c# asp.net-core entity-framework-core asp.net-identity-3

应用:Asp.NET Core 1.1.1,EF Core

平台:Visual Studio 2017 5.3.3

身份验证模式:个人用户帐户

在ASP.NET官方团队的this tutorial之后,以下命令成功运行:

PM> Add-Migration MyFirstMigration -context BloggingContext

我们知道{默认VS2017默认情况下会在MyProject \ Data文件夹下创建ApplicationDbContext,以便创建用户表(ASPNETUsers, ASPNETRoles etc...)进行身份验证。但是,当我运行以下命令时,它首先在下面给我Error-1。当我按照第一条错误消息中的说明操作时,我会在下方获得Error-2问题:如何使用IDbContextFactory使以下命令不使用

PM> Add-Migration MyFirstAuthenMigration -context ApplicationDbContext

错误1

  

在' ApplicationDbContext'上找不到无参数构造函数。将无参数构造函数添加到' ApplicationDbContext'或者添加' IDbContextFactory'的实现在与#D; ApplicationDbContext'。

相同的程序集中

ApplicationDbContext.cs中添加无参数构造函数后(如下所示),我得到如下所示的第二个错误:

错误2

  

没有为此DbContext配置数据库提供程序。可以通过覆盖DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext来配置提供程序。如果使用AddDbContext,那么还要确保您的DbContext类型在其构造函数中接受DbContextOptions对象,并将其传递给DbContext的基础构造函数。

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);
    }
}

1 个答案:

答案 0 :(得分:0)

你无法让它发挥作用。 因为EF需要知道应该使用哪个连接字符串。您可以将connectionstring放入OnModelCreating方法。 当你有多个数据库(例如开发,测试和生产)时哪个很糟糕。 或者你实现了IDbContextFactory,它将由EF通过反射加载。

因此,实现IDbContextFactory是更好的选择。只需在拥有ApplicationDbContext的地方创建它。 示例实施。

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);
}

它适用于3个配置文件(最终,本地和测试)

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

用法如下所示:

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);

    }
}

在MSVC中使用“Add-Migration”也可以。