实体框架核心迁移 - 连接字符串

问题描述 投票:11回答:3

我在处理数据库连接字符串和迁移时遇到问题。我有2个项目:

  • 应用

DbContext位于Domain项目中,因此这是我运行迁移的项目。迁移概念强制我在我的OnConfiguring中实现DbContext,并在其中指定数据库提供程序,例如:

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

我的问题是我不想使用硬编码连接字符串,原因很明显,我不能使用ConfigurationManager从配置文件中读取它,因为配置文件在应用程序项目中。

c# .net-core entity-framework-core ef-migrations
3个回答
4
投票

我见过的所有示例都涉及对连接字符串进行硬编码或将其放入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

1
投票

我们遇到了同样的问题并且有一个解决方案。 :)

您必须实现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
投票

这就是我如何做到这一点,没有太多额外的代码或疯狂。

项目结构:

  • Asp Net Core Project.Web
  • AspNetCoreProject.Data < - DbContext here

我的DbContext是使用允许您注入DbContextOptions的构造函数设置的

asp net core project.data

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

在您的应用程序或Web应用程序中,您可以正常设置ConfigureServices

AspNetCoreProject.Web / Startup.cs / ConfigureServices()

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

现在,迁移呢?好吧,我“欺骗”Visual Studio UI按预期工作。

  • 首先,确保您的应用程序(AspNetCoreProject.Web项目与Startup.cs)是start up project
  • 其次,打开Nuget Package Manager控制台。在Nuget PM>控制台的顶部,有一个“设置默认项目”的下拉列表,使用AspNetCoreProject.Data类将其指向DbContext或项目。
  • 正常运行你的migration commandsadd-migration init然后update-database
© www.soinside.com 2019 - 2024. All rights reserved.