应用: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);
}
}
答案 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个配置文件(最终,本地和测试)
用法如下所示:
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”也可以。