web-dev-qa-db-ja.com

.NET Core 2.0アプリでハードコーディングされるのではなく、appsettings.jsonからConnectionStringを取得します

NET Core2.0アプリには次のクラスがあります。

// required when local database does not exist or was deleted
public class ToDoContextFactory : IDesignTimeDbContextFactory<AppContext>
{
    public AppContext CreateDbContext(string[] args)
    {
        var builder = new DbContextOptionsBuilder<AppContext>();
        builder.UseSqlServer("Server=localhost;Database=DbName;Trusted_Connection=True;MultipleActiveResultSets=true");
        return new AppContext(builder.Options);
    }
}

これは、データベースが存在せず、実行時に作成する必要があるupdate-databaseの場合、移行を伴うCore 2.0で必要です。
ASP.NET Core 2.0へのアップグレード後に移行を作成できません

ConnectionStringを2か所(こことappsettings.json)ではなく、.jsonだけにしたいので、置き換えようとしました

"Server=localhost;Database=DbName;Trusted_Connection=True;MultipleActiveResultSets=true"

ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString

しかし、それは機能していません、私はヌル値を取得しています。

更新1:
コア2では.jsonを明示的に追加する必要がないため、ファイルに問題はありません。
https://andrewlock.net/exploring-program-and-startup-in-asp-net-core-2-preview1-2/

更新2:
また、.jsonからContextにConnectionStringを送信するためにすでに構成を使用しています。

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<AppContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    }
}

しかし、構成がないため、ToDoContextFactoryにこれを使用することはできません。ToDoContextFactoryは移行によって使用されるため、アプリはまったく実行されません。

解決策:@JRBからの回答に基づいて、次のように動作させました。

public AppContext CreateDbContext(string[] args)
{
    string projectPath = AppDomain.CurrentDomain.BaseDirectory.Split(new String[] { @"bin\" }, StringSplitOptions.None)[0];
    IConfigurationRoot configuration = new ConfigurationBuilder()
        .SetBasePath(projectPath)
        .AddJsonFile("appsettings.json")
        .Build();
    string connectionString = configuration.GetConnectionString("DefaultConnection");

    var builder = new DbContextOptionsBuilder<AppContext>();
    builder.UseSqlServer(connectionString);

    return new AppContext(builder.Options);
}
41
borisdj

ステップ1:OnConfiguring()に以下を含めます

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
            .AddJsonFile("appsettings.json")
            .Build();
        optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
    }

ステップ2:appsettings.jsonを作成します。

  {
    "ConnectionStrings": {       
      "DefaultConnection": "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"        
    } 
  }

ステップ3:appsettings.jsonを正しいディレクトリにハードコピーします

  Hard copy appsettings.json.config to the directory specified in the AppDomain.CurrentDomain.BaseDirectory directory. 
  Use your debugger to find out which directory that is.        

前提:既にMicrosoft.Extensions.Configuration.Jsonパッケージ(Nugetから取得)をプロジェクトに含めていること。

54
JRB

ASPNET Coreでは、Startup.csでそれを行います

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<BloggingContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase")));
}

接続はappsettings.jsonで定義されています

{
  "ConnectionStrings": {
    "BloggingDatabase": "..."
  },
}

MS docs の例

6
Roman Gudkov

IDesignTimeDbContextFactoryを実装し、設定ファイルのコピーを行うことなく、この結果を達成するために使用できるデフォルトパターンが実際にあります。

this doc で詳しく説明されています。フレームワークが設計時にDbContextのインスタンス化を試みる他の方法についても説明しています。

具体的には、新しいフック、この場合はpublic static IWebHost BuildWebHost(string[] args)という形式の静的メソッドを利用します。ドキュメントはそうではないことを暗示していますが、このメソッドは、エントリポイントを収容するクラスに存在できます( src を参照)。これを実装することは、 1.xから2.xへの移行ドキュメント のガイダンスの一部であり、コードを見て完全に明らかではないのは、 WebHost.CreateDefaultBuilder(args)は、とりわけ、新しいプロジェクトが開始するデフォルトのパターンで構成を接続することです。移行などの設計時サービスで使用される構成を取得するために必要なのはそれだけです。

ここで何が起こっているかについての詳細を以下に示します。

移行の追加中に、フレームワークがDbContextを作成しようとすると、 first が検出したIDesignTimeDbContextFactory実装を、使用可能なファクトリメソッドのコレクションに追加しますコンテキストを作成するには、前述の静的フックを介して構成済みのサービスを取得し、DbContextOptionsで登録されたコンテキストタイプに対して looks を取得します(これはStartup.ConfigureServicesAddDbContextまたはAddDbContextPoolを使用する場合)およびそれらのファクトリーを追加します。最後に、それは すべてのDbContext派生クラスのアセンブリを検索し 、最終的なあられとしてActivator.CreateInstanceを呼び出すファクトリメソッドを作成します。

フレームワークが使用する優先順位は、上記と同じです。したがって、IDesignTimeDbContextFactoryを実装している場合、上記のフックをオーバーライドします。ただし、最も一般的なシナリオでは、IDesignTimeDbContextFactoryは必要ありません。

4
Erikest

それをそのクラスへのDPインジェクションとして渡すのはどうですか? ConfigureServicesで:

services.Configure<MyOptions>(Configuration);

jSON文字列を保持するクラスを作成します。

public class MyOptions
{
    public MyOptions()
    {

    }
    public string Option1 { get; set; }
    public string Option2 { get; set; }
}    

Jsonファイルに文字列を追加します。

"option1": "somestring",
"option2": "someothersecretstring"

これらの文字列を必要とするクラスでは、コンストラクターとして渡します。

public class SomeClass
{
 private readonly MyOptions _options;

    public SomeClass(IOptions<MyOptions> options)
    {
        _options = options.Value;           
    }    

 public void UseStrings()
 {
   var option1 = _options.Option1;
    var option2 = _options.Option2;
 //code
 }
}
3
Johan Herstad

私はこれが回答済みとマークされていることを理解していますが、残りのプロジェクトから分離された.DLLプロジェクトでEF Core Data Access Layerがあるプロジェクトで作業しているときに少し問題に遭遇しました私のプロジェクト、API、Auth、およびWebであり、主に他のプロジェクトがこのデータプロジェクトを参照することを好みます。そして、接続プロジェクトを毎回変更するためにデータプロジェクトに参加したくありません。

ステップ1:これをOnConfiguringメソッドに含める

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
      {
           var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
           IConfigurationRoot configuration = new ConfigurationBuilder()
                **.SetBasePath(Path.Combine(Directory.GetCurrentDirectory()))**
                .AddJsonFile("appsettings.json", optional: false)
                .AddJsonFile($"appsettings.{envName}.json", optional: false)
                .Build();
           optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
      }

注:.SetBasePath(Path.Combine(Directory.GetCurrentDirectory()))これは、ASP.NET COREが適切に選択できるほどスマートであるため、ファイルをディレクトリにコピーする必要性を無効または無効にしますファイル。また、Prod環境ファイルが選択されていると仮定して、リリースまたは実動用のビルド時に指定された環境が正しいファイルを選択します。

ステップ2:appsettings.jsonを作成する

{
"ConnectionStrings": {       
  "DefaultConnection": "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"        
} 

}

ご注意:参照:Microsoft.Extensions.Configuration

1
Ismail Umar
  1. 次のコードをstartup.csファイルに追加します。

    public void ConfigureServices(IServiceCollection services)
    {
        string con = Configuration.GetConnectionString("DBConnection");
        services.AddMvc();
        GlobalProperties.DBConnection = con;//DBConnection is a user defined static property of GlobalProperties class
    }
    
  2. ContextクラスでGlobalProperties.DBConnectionプロパティを使用します。

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {  
              optionsBuilder.UseSqlServer(GlobalProperties.DBConnection);
        }
    }
    
0

appSettings.jsonファイルで接続文字列を定義することにより、ASP.NET Core 2でこれを行うこともできます。次に、Startup.csで、使用する接続文字列を指定します。

appSettings.json

{
    "connectionStrings": {
        "YourDBConnectionString": "Server=(localdb)\\mssqllocaldb;Database=YourDB;Trusted_Connection=True"
    }
}

Startup.cs

public static IConfiguration Configuration { get; private set;}

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}
var connectionString = Configuration["connectionStrings:YourDBConnectionString"];
services.AddDbContext<YourDbContext>(x => x.UseSqlServer(connectionString));
0