我可以將依賴注入遷移(使用EF-Core代碼優先遷移)嗎?

asp.net-core dependency-injection ef-migrations entity-framework entity-framework-core

我試圖將IConfiguration注入遷移(在構造函數中),並得到異常:“沒有為此對象定義無參數構造函數。”

任何解決方法?

一般承認的答案

您不能,遷移需要能夠在您的應用程序的上下文之外運行。

由於Entity-framework命令行工具分析您的代碼但不運行startup.cs類。

它也是不可取的。您的遷移應該簡單明了,不依賴於任何東西。如果它會,它可能會導致主要的運行時副作用,其中缺少配置可能導致生產中缺少表或列。

額外的建議

如果它涉及很多小/相等/手動變化。最好的方法是生成遷移文件。為什麼?這樣,您的遷移將具有確定性:您知道結果將是什麼。如果遷移中的某一行失敗,那麼簡單明了,為什麼那麼容易(呃)可修復。


熱門答案

有辦法做你想做的事。在我的場景中,我想通過DbContext在連接字符串中使用數據庫名稱。使用EF核心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);
    }
}

用您的自定義類替換DbContext中的IMigrationAssembly服務

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.ReplaceService<IMigrationsAssembly, ContextAwareMigrationsAssembly>();
}

然後,您可以在遷移中添加DbContext參數。

public Migration20180801(DbContext context)
{
    DatabaseName = context.Database.GetDbConnection().Database;
}

在您的情況下,您可以使用IConfigurationCreateMigration覆蓋中的相關實例替換所有DbContext引用。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow