簡體   English   中英

Entity Framework Core 遷移 - 連接字符串

[英]Entity Framework Core migration - connection string

我在處理數據庫連接字符串和遷移時遇到了問題。 我有2個項目:

  • 領域
  • 應用

DbContext在域項目中,所以這是我運行遷移的項目。 遷移概念強制我在我的DbContext實現OnConfiguring並在其中指定數據庫提供程序,例如:

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

我的問題是我不想使用硬編碼的連接字符串,原因很明顯,我不能使用 ConfigurationManager 從配置文件中讀取它,因為配置文件在應用程序項目中。

我見過的所有示例都涉及對連接字符串進行硬編碼或將其放入我的 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

這是我如何做到的,沒有很多額外的代碼或瘋狂。

項目結構:

  • AspNetCoreProject.Web

  • AspNetCoreProject.Data <-- DbContext here

我的 DbContext 是使用構造函數設置的,該構造函數允許您注入 DbContextOptions

AspNetCoreProject.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 使其按預期工作。

  • 首先,確保您的應用程序(帶有Startup.cs AspNetCoreProject.Web項目)是啟動項目

  • 其次,打開您的 Nuget 包管理器控制台。 在 Nuget PM> 控制台的頂部,有一個“設置默認項目”的下拉菜單,將其指向您的AspNetCoreProject.Data或帶有DbContext類的項目。

  • 正常運行遷移命令 add-migration init然后update-database

我們遇到了同樣的問題,並且有一個解決方案。 :)

您必須實現IDbContextFactory<TContext>這樣做時,您可以從 appsettings.json 讀取連接字符串。 您還可以OnConfigure()使用 Add-Migration,因為OnConfigure()覆蓋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"
  }
}

我在 Windows 環境變量MsSql.ConnectionString中使用下面的MsSql.ConnectionString和初始 ef 遷移創建命令開始工作: dotnet ef migrations add InitialCreate

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    var connectionString = Environment.GetEnvironmentVariable("MsSql.ConnectionString");
    if(string.IsNullOrEmpty(connectionString))
        throw new ConfigurationErrorsException("Sql server connection string configuration required");
    
    if (!optionsBuilder.IsConfigured)
    {
        optionsBuilder
            .UseSqlServer(connectionString)
            .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
    }
}

配置環境變量:

  1. 使用Win + R熱鍵組合打開Run命令窗口
  2. 鍵入systempropertiesadvanced並按 Enter
  3. Advanced選項卡上單擊Environment Variables
  4. 單擊New...按鈕
  5. Variable name字段中鍵入MsSql.ConnectionString
  6. Variable value字段中鍵入您的連接字符串值

確保在添加新變量之后和運行dotnet ef相關命令之前重新啟動控制台(以及啟動控制台的任何程序)

我的控制台應用程序中有我的 DBContext,並且使用了一個參數很少(例如連接字符串等)的 ctor,因為 EF Core Migrations 使用的是默認參數 less ctor,因此沒有填充連接字符串我有遷移失敗.

剛剛添加了代碼以從我的默認構造函數中的 ConfigurationBuilder 獲取連接字符串以繞過它。

只是在玩控制台應用程序和 EF Core,所以現在這對我有用。

假設您的 DbContext 類具有接受 DbContextOptions 類型參數的構造函數,則 dotnet ef 命令對這種情況具有本機支持 - 無需更改代碼或額外配置。 創建和運行遷移時只需使用“--startup-project”和“--project”參數。

例如,假設您有一個帶有配置的“應用程序”項目和一個名為“域”的單獨項目,其中實現了 DbContext。

語境:

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

啟動:

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

命令行命令:

dotnet ef database update --startup-project Application --project Domain

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM