Andamios de migración de Entity Framework 7 en la biblioteca de clases con configuración

asp.net-core code-first-migrations dnx entity-framework-core visual-studio-2015

Pregunta

Intentando agregar migraciones a un modelo EF7 que vive en una biblioteca de clases ASP.NET 5. Cuando se ejecuta dnx . ef migration add mymigration falla con resultados diferentes según el proyecto en el que lo ejecute.

Si lo ejecuto en la carpeta del proyecto principal, no puede ubicar un DbContext , esto tiene sentido porque DbContext está en el proyecto compartido y los comandos ef probablemente no se preocupan por las dependencias.

Si lo ejecuto en la carpeta del proyecto compartido, no tiene acceso a la cadena de conexión especificada en startup.cs. He deducido de preguntas como esta que funciona desde el proyecto compartido si especifica la cadena de conexión en el método OnConfiguring del DbContext pero realmente me gustaría mantener este código separado de la configuración.

Encontré algunos registros de problemas en el repositorio de EF7 que mencionan que implementaron opciones de línea de comandos para especificar un proyecto y un contexto, pero no hay ejemplos y no pude averiguar cómo usarlo mirando el código fuente en el historial de confirmación. .

Respuesta aceptada

Aquí hay un enfoque que podría funcionar para usted.

Si lo ejecuto en la carpeta del proyecto compartido, no tiene acceso a la cadena de conexión especificada en startup.cs.

Startup.cs

Supongo que en su Startup.cs, está especificando la cadena de conexión accediendo a Configuration lugar de codificarla. Además, asumo que en el constructor del archivo Startup.cs, está configurando la configuración desde algunas fuentes. En otras palabras, su Startup.cs podría verse así:

public class Startup
{
    public IConfiguration Config { get; set; }

    public Startup(IHostingEnvironment env)
    {
        var config = new Configuration()
            .AddJsonFile("config.json")
            .AddUserSecrets()
            .AddEnvironmentVariables();

        Config = config;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<MyDbContext>(options =>
            {
                options.UseSqlServer(Config["ConnectionStrings:MyDbContext"]);
            });
    }

    public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
    {
        var db = serviceProvider.GetRequiredService<MyDbContext>();
        db.Database.AsSqlServer().EnsureCreated();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
}

config.json

Además, asumo que está agregando la cadena de conexión a un config.json en la raíz de su proyecto (o que lo está agregando a través de secretos de usuario o variables de entorno). Su config.json podría tener este aspecto:

public class Startup
{
    public IConfiguration Config { get; set; }

    public Startup(IHostingEnvironment env)
    {
        var config = new Configuration()
            .AddJsonFile("config.json")
            .AddUserSecrets()
            .AddEnvironmentVariables();

        Config = config;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<MyDbContext>(options =>
            {
                options.UseSqlServer(Config["ConnectionStrings:MyDbContext"]);
            });
    }

    public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
    {
        var db = serviceProvider.GetRequiredService<MyDbContext>();
        db.Database.AsSqlServer().EnsureCreated();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
}

Si no lo haces de esa manera, podría valer la pena intentarlo.

He deducido de preguntas como esta que funciona desde el proyecto compartido si especifica la cadena de conexión en el método OnConfiguring del DbContext pero realmente me gustaría mantener este código separado de la configuración.

DbContext

Si mis suposiciones anteriores son correctas, entonces puede acceder a la cadena de conexión en DbContext usando el mismo patrón que usó en la clase de Startup . Es decir, en el constructor DbContext , configure la IConfiguration . Luego, en OnConfiguring , acceda a la cadena de conexión. Podría verse algo como esto:

public class Startup
{
    public IConfiguration Config { get; set; }

    public Startup(IHostingEnvironment env)
    {
        var config = new Configuration()
            .AddJsonFile("config.json")
            .AddUserSecrets()
            .AddEnvironmentVariables();

        Config = config;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<MyDbContext>(options =>
            {
                options.UseSqlServer(Config["ConnectionStrings:MyDbContext"]);
            });
    }

    public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
    {
        var db = serviceProvider.GetRequiredService<MyDbContext>();
        db.Database.AsSqlServer().EnsureCreated();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
}

Estructura del proyecto

Por supuesto, también deberá tener un archivo config.json en la raíz de la carpeta de proyectos compartidos. Entonces, la estructura de sus proyectos podría verse así:

public class Startup
{
    public IConfiguration Config { get; set; }

    public Startup(IHostingEnvironment env)
    {
        var config = new Configuration()
            .AddJsonFile("config.json")
            .AddUserSecrets()
            .AddEnvironmentVariables();

        Config = config;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<MyDbContext>(options =>
            {
                options.UseSqlServer(Config["ConnectionStrings:MyDbContext"]);
            });
    }

    public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
    {
        var db = serviceProvider.GetRequiredService<MyDbContext>();
        db.Database.AsSqlServer().EnsureCreated();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
}

En lo anterior, ambos archivos config.json contienen una configuración de cadena de conexión para DbContext .

Algunos pensamientos

Si no te gusta duplicar las cosas de la cadena de conexión config.json, entonces puedes usar variables de entorno o secretos de usuario.




Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué