Entity Framework 7 Scaffolding di migrazione nella libreria di classi con configurazione

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

Domanda

Tentativo di aggiungere migrazioni a un modello EF7 che risiede in una libreria di classi ASP.NET 5. Quando si esegue dnx . ef migration add mymigration fallisce con risultati diversi a seconda del progetto su cui lo dnx . ef migration add mymigration .

Se lo DbContext nella cartella del progetto principale, non è in grado di individuare un DbContext , questo ha senso perché DbContext trova nel progetto condiviso e i comandi ef probabilmente non si preoccupano delle dipendenze.

Se lo eseguo nella cartella del progetto condiviso, non ha accesso alla stringa di connessione specificata in startup.cs. Ho raccolto da domande come questa che funziona dal progetto condiviso se si specifica la stringa di connessione nel metodo OnConfiguring del DbContext ma mi piacerebbe davvero mantenere questo codice separato dalla configurazione.

Ho trovato alcuni registri di problemi nel repository EF7 che menzionavano l'implementazione delle opzioni della riga di comando per specificare un progetto e un contesto ma non ci sono esempi e non sono riuscito a capire come usarlo guardando il codice sorgente nella cronologia dei commit .

Risposta accettata

Ecco un approccio che potrebbe funzionare per te.

Se lo eseguo nella cartella del progetto condiviso, non ha accesso alla stringa di connessione specificata in startup.cs.

Startup.cs

Suppongo che nel tuo Startup.cs, stai specificando la stringa di connessione accedendo a Configuration piuttosto che codificandola con cura. Inoltre, presumo che nel costruttore del file Startup.cs, stai configurando la configurazione da poche fonti. In altre parole, il tuo Startup.cs potrebbe assomigliare a questo:

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

Inoltre, presumo che tu stia aggiungendo la stringa di connessione a un config.json nella radice del tuo progetto (o che lo aggiungi tramite i segreti dell'utente o le variabili ambientali). Il tuo file config.json potrebbe essere qualcosa del genere:

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!");
        });
    }
}

Se non lo fai in questo modo, potrebbe valere la pena provarlo.

Ho raccolto da domande come questa che funziona dal progetto condiviso se si specifica la stringa di connessione nel metodo OnConfiguring del DbContext, ma mi piacerebbe davvero mantenere questo codice separato dalla configurazione.

DbContext

Se le mie supposizioni di cui sopra sono corrette, puoi accedere alla stringa di connessione in DbContext usando lo stesso pattern che hai usato nella classe Startup . Vale a dire, nel costruttore DbContext , configurare IConfiguration . Quindi, in OnConfiguring , accedi alla stringa di connessione. Potrebbe sembrare qualcosa del genere:

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!");
        });
    }
}

Struttura del progetto

Ovviamente dovrai anche avere un file config.json nella radice della cartella dei progetti condivisi. Quindi, la struttura dei tuoi progetti potrebbe essere simile a questa:

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!");
        });
    }
}

In precedenza, entrambi i file config.json contengono un'impostazione di stringa di connessione per DbContext .

Alcuni pensieri

Se non ti piace duplicare la stringa di connessione config.json, puoi utilizzare invece variabili ambientali o segreti utente.




Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché