我可以将依赖注入迁移(使用EF-Core代码优先迁移)吗?

ari*_*its 11 entity-framework dependency-injection ef-migrations entity-framework-core asp.net-core

我试图注入IConfiguration迁移(在构造函数中),并得到异常:"没有为此对象定义无参数构造函数."

任何解决方法?

Joe*_*kes 11

您不能,迁移需要能够在您的应用程序的上下文之外运行.

由于Entity-framework命令行工具分析您的代码但不运行startup.cs类.

它也是不可取的.您的迁移应该简单明了,不依赖于任何东西.如果它会,它可能会导致主要的运行时副作用,其中缺少配置可能导致生产中缺少表或列.

额外的建议

如果它涉及很多小/相等/手动变化.最好的方法是生成迁移文件.为什么?这样,您的迁移将具有确定性:您知道结果将是什么.如果迁移中的某一行失败,那么简单明了,为什么那么容易(呃)可修复.

  • “迁移需要能够在应用程序的上下文之外运行”。错误(至少在当前版本的 EF 中)。EF 工具使用您的程序主机构建器来发现创建和执行迁移所需的所有服务和配置。 (4认同)

Mar*_*pez 5

有一种方法可以做您想做的事。在我的方案中,我想通过DbContext在连接字符串中使用数据库名称。使用EF core 2.1.1。代码从这里修改

创建自定义的MigrationsAssembly服务

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Internal;
using System;
using System.Reflection;

public class ContextAwareMigrationsAssembly : MigrationsAssembly
{
    private readonly DbContext context;

    public ContextAwareMigrationsAssembly(
        ICurrentDbContext currentContext,
        IDbContextOptions options,
        IMigrationsIdGenerator idGenerator,
        IDiagnosticsLogger<DbLoggerCategory.Migrations> logger) : base(currentContext, options, idGenerator, logger)
    {
        context = currentContext.Context;
    }

    /// <summary>
    /// Modified from http://weblogs.thinktecture.com/pawel/2018/06/entity-framework-core-changing-db-migration-schema-at-runtime.html
    /// </summary>
    /// <param name="migrationClass"></param>
    /// <param name="activeProvider"></param>
    /// <returns></returns>
    public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider)
    {
        var hasCtorWithDbContext = migrationClass
                .GetConstructor(new[] { typeof(DbContext) }) != null;

        if (hasCtorWithDbContext)
        {
              var instance = (Migration)Activator.CreateInstance(migrationClass.AsType(), context);
              instance.ActiveProvider = activeProvider;
              return instance;
        }

        return base.CreateMigration(migrationClass, activeProvider);
    }
}
Run Code Online (Sandbox Code Playgroud)

用自定义类替换DbContext中的IMigrationAssembly服务

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.ReplaceService<IMigrationsAssembly, ContextAwareMigrationsAssembly>();
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以DbContext在迁移中添加参数。

public Migration20180801(DbContext context)
{
    DatabaseName = context.Database.GetDbConnection().Database;
}
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您可以将所有DbContext引用替换为,IConfiguration并在CreateMigration覆盖中替换相关实例。

  • 有人真的用 IConfiguration 尝试过这个吗?我尝试将 IConfiguration 注入到 ContextAwareMigrationsAssembly 这样的类中,但没有解决。 (2认同)