Can I inject dependency into migration (using EF-Core code-first migrations)?

前端 未结 3 1110
感动是毒
感动是毒 2021-02-19 03:20

I tried to inject IConfiguration into the migration (in constructor), and got exception: \"No parameterless constructor defined for this object.\"

any worka

3条回答
  •  感动是毒
    2021-02-19 03:56

    There's a way to do what you want to do. In my scenario, I would like to use the database name in the connection string through the DbContext. EF core 2.1.1 is used. The code is modified from here

    Create a custom MigrationsAssembly service

    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 logger) : base(currentContext, options, idGenerator, logger)
        {
            context = currentContext.Context;
        }
    
        /// 
        /// Modified from http://weblogs.thinktecture.com/pawel/2018/06/entity-framework-core-changing-db-migration-schema-at-runtime.html
        /// 
        /// 
        /// 
        /// 
        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);
        }
    }
    

    Replace the IMigrationAssembly service in your DbContext with your custom class

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.ReplaceService();
    }
    

    Then you can add a DbContext parameter in your migration.

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

    In your case, you can replace all the DbContext references with IConfiguration and the relevant instance in the CreateMigration override.

提交回复
热议问题