Entity Framework Core migration - connection string

I had a problem processing a DB connection string in conjunction with migrations. I have 2 projects:

  • Domain
  • Application

DbContextis in the Domain project, so this is the project I'm running migrations with. The migration concept obliged me to implement OnConfiguringin my DbContextand in it indicate the database provider, for example:

protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
    builder.UseSqlServer("<connection string>");
}

My problem is that I do not want to use a hard-coded connection string for obvious reasons, and I cannot use the ConfigurationManager to read it from the configuration file, since the configuration file is in the application project.

+10
source share
3 answers

, , , ASP.NET Core.

ASP.NET Core , , , , , .

-, IDesignTimeDbContextFactory ( , IDbContextFactory ):

public class AppContextFactory: IDesignTimeDbContextFactory<AppContext>
{
    public AppContextFactory()
    {
        // A parameter-less constructor is required by the EF Core CLI tools.
    }

    public AppContext CreateDbContext(string[] args)
    {
        var connectionString = Environment.GetEnvironmentVariable("EFCORETOOLSDB");
        if (string.IsNullOrEmpty(connectionString))
            throw new InvalidOperationException("The connection string was not set " +
            "in the 'EFCORETOOLSDB' environment variable.");

         var options = new DbContextOptionsBuilder<AppContext>()
            .UseSqlServer(connectionString)
            .Options;
        return new AppContext(options);
    }
}

Update-Database EF Core:

$env:EFCORETOOLSDB = "Data Source=(local);Initial Catalog=ApplicationDb;Integrated Security=True"; Update-Database
+2

, .:)

IDbContextFactory <TContext> appsettings.json. Add-Migration , OnConfigure() .

:

public class DomainContextFactory : IDbContextFactory<DomainContext>
{
    public string BasePath { get; protected set; }

    public DomainContext Create()
    {
        var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

        var basePath = AppContext.BaseDirectory;

        return Create(basePath, environmentName);
    }

    public DomainContext Create(DbContextFactoryOptions options)
        => Create(options.ContentRootPath, options.EnvironmentName);

    private DomainContext Create(string basePath, string environmentName)
    {
        BasePath = basePath;
        var configuration = Configuration(basePath, environmentName);
        var connectionString = ConnectionString(configuration.Build());
        return Create(connectionString);
    }

    private DomainContext Create(string connectionString)
    {
        if (string.IsNullOrEmpty(connectionString))
        {
            throw new ArgumentException($"{nameof(connectionString)} is null or empty", nameof(connectionString));
        }
        var optionsBuilder = new DbContextOptionsBuilder<DomainContext>();
        return Configure(connectionString, optionsBuilder);
    }

    protected virtual IConfigurationBuilder Configuration(string basePath, string environmentName)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(basePath)
            .AddJsonFile("constr.json")
            .AddJsonFile($"constr.{environmentName}.json", true)
            .AddEnvironmentVariables();
        return builder;
    }

    protected virtual string ConnectionString(IConfigurationRoot configuration)
    {
        string connectionString = configuration["ConnectionStrings:DefaultConnection"];
        return connectionString;
    }

    protected virtual DomainContext Configure(string connectionString, DbContextOptionsBuilder<DomainContext> builder)
    {
        builder.UseSqlServer(connectionString, opt => opt.UseRowNumberForPaging());

        DomainContext db = new DomainContext(builder.Options);
        return db;
    }


    DomainContext IDbContextFactory<DomainContext>.Create(DbContextFactoryOptions options)
        => Create(options.ContentRootPath, options.EnvironmentName);
}

:

    public override IServiceResult<IList<Datei>> LoadAllData()
    {
        using (var db = this.DomainContextFactory.Create())
        {
            var files = db.Datei
                .ToListAsync<Datei>();

            return new ServiceResult<IList<Datei>>(files.Result, files.Result.Count);
        }
    }

{
  "ConnectionStrings": {
    "DefaultConnection": "Put your connectionstring here"
  }
}
+1

, .

:

  • AspNetCoreProject.Web

  • AspNetCoreProject.Data <- DbContext

DbContext , DbContextOptions

AspNetCoreProject.Data

public class MyContext : DbContext
{
    public MyContext(DbContextOptions<MyContext> options) : base(options)
    {
    }
}

- ConfigureServices .

AspNetCoreProject.Web/Startup.cs/ConfigureServices()

services.AddDbContext<MyContext>(options => 
            options.UseSqlServer(Configuration.GetConnectionString("connection"))

? , "" Visual Studio, .

  • -, , ( AspNetCoreProject.Web Startup.cs) .

  • Second, open the Nuget Package Manager console. At the top of the Nuget PM> Console console there is a drop-down list "Set project as default", point it to your AspNetCoreProject.Dataor project with a class DbContext.

  • Run your migration commands as usual. add-migration initthenupdate-database

+1
source

Source: https://habr.com/ru/post/1689780/


All Articles