Я попытался ввести IConfiguration
в перенос (в конструкторе) и получил исключение: "Без конструктора без параметров для этого объекта".
любой обходной путь?
Я попытался ввести IConfiguration
в перенос (в конструкторе) и получил исключение: "Без конструктора без параметров для этого объекта".
любой обходной путь?
вы не можете, миграции должны быть в состоянии работать вне контекста вашего приложения.
Поскольку инструмент командной строки Entity-framework анализирует ваш код, но не запускает класс startup.cs.
Также это не рекомендуется. Ваши миграции должны быть простыми и не зависеть ни от чего. в противном случае это может привести к серьезным побочным эффектам во время выполнения, когда отсутствие конфигурации может привести к отсутствию таблиц или столбцов в рабочей среде.
Если это включает в себя много небольших/равных/ручных изменений. Лучший способ - создать файл миграции. Зачем? Таким образом, ваша миграция будет детерминированной: вы знаете, каков будет результат. Если в вашей миграции произошел сбой, просто и понятно, почему это можно и легко исправить.
Есть способ сделать то, что вы хотите сделать. В моем сценарии я хотел бы использовать имя базы данных в строке подключения через 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);
}
}
Замените службу IMigrationAssembly в вашем DbContext на ваш собственный класс
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.ReplaceService<IMigrationsAssembly, ContextAwareMigrationsAssembly>();
}
Затем вы можете добавить параметр DbContext
в вашу миграцию.
public Migration20180801(DbContext context)
{
DatabaseName = context.Database.GetDbConnection().Database;
}
В вашем случае, вы можете заменить все DbContext
ссылки с IConfiguration
и соответствующий экземпляр в CreateMigration
переопределения.
Если речь идет только о вашей строке подключения (не так ли?), Вы можете проверить этот ответ, который в основном предлагает этот код в вашем проекте запуска (не в вашем проекте миграции):
var myConnectionString = Configuration.GetConnectionString(myConnectionStringName);
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(
myConnectionString ,
x => x.MigrationsAssembly(myDbContextAssemblyName)));