移行に関連してDB接続文字列を処理するのに問題があります。 2つのプロジェクトがあります。
DbContext
はDomainプロジェクトにあるため、これは移行を実行するプロジェクトです。移行の概念により、OnConfiguring
にDbContext
を実装し、データベースプロバイダーを指定するように強制されます。例:
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はこちら
私の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を期待通りに「だまします」。
最初に、アプリケーション(_AspNetCoreProject.Web
_プロジェクト(_Startup.cs
_を含む)が スタートアッププロジェクト であることを確認します。
次に、Nuget Package Managerコンソールを開きます。 Nuget PM>コンソールの上部に、 'Set Default Project'のドロップダウンがあり、これを_AspNetCoreProject.Data
_またはDbContext
クラスのプロジェクトにポイントします。
移行コマンド を通常どおり実行します。 _add-migration init
_その後_update-database
_
同じ問題があり、解決策があります。 :)
IDbContextFactory <TContext> を実装する必要があります。これを行うと、appsettings.jsonから接続文字列を読み取ることができます。 OnConfigure()
の上書きは廃止されるため、Add-Migrationをエラーなしで使用することもできます。
サンプル実装:
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"
}
}