Mar*_*ert 6 entity-framework-core entity-framework-core-migrations
我使用 IDesignTimeDbContextFactory<> 模式在单独的程序集中定义了一个 Entity Framework Core 数据库(即,我定义一个派生自 IDesignTimeDbContextFactory 的类,该类具有一个名为 CreateDbContext 的方法,该方法返回数据库上下文的实例)。
由于 EF Core 数据库所属的应用程序使用 AutoFac 依赖注入,因此 IDesignTimeDbContextFactory<> 工厂类在其构造函数中创建 AutoFac 容器,然后解析 DbContextOptionsBuilder<> 派生类,该类被馈送到数据库的构造函数中(我这样做是为了根据配置文件设置,控制是否将本地数据库或基于 Azure 的 SqlServer 数据库作为目标,并将密码存储在 Azure KeyVault 中):
public class TemporaryDbContextFactory : IDesignTimeDbContextFactory<FitchTrustContext>
{
private readonly FitchTrustDBOptions _dbOptions;
public TemporaryDbContextFactory()
{
// OMG, I would >>never<< have thought to do this to eliminate the default logging by this
// deeply-buried package. Thanx to Bruce Chen via
// /sf/ask/3358753611/#48016958
LoggerCallbackHandler.UseDefaultLogging = false;
var builder = new ContainerBuilder();
builder.RegisterModule<SerilogModule>();
builder.RegisterModule<KeyVaultModule>();
builder.RegisterModule<ConfigurationModule>();
builder.RegisterModule<FitchTrustDbModule>();
var container = builder.Build();
_dbOptions = container.Resolve<FitchTrustDBOptions>() ??
throw new NullReferenceException(
$"Could not resolve {typeof(FitchTrustDBOptions).Name}");
}
public FitchTrustContext CreateDbContext( string[] args )
{
return new FitchTrustContext( _dbOptions );
}
}
public class FitchTrustDBOptions : DbContextOptionsBuilder<FitchTrustContext>
{
public FitchTrustDBOptions(IFitchTrustNGConfigurationFactory configFactory, IKeyVaultManager kvMgr)
{
if (configFactory == null)
throw new NullReferenceException(nameof(configFactory));
if (kvMgr == null)
throw new NullReferenceException(nameof(kvMgr));
var scannerConfig = configFactory.GetFromDisk()
?? throw new NullReferenceException(
"Could not retrieve ScannerConfiguration from disk");
var dbConnection = scannerConfig.Database.Connections
.SingleOrDefault(c =>
c.Location.Equals(scannerConfig.Database.Location,
StringComparison.OrdinalIgnoreCase))
?? throw new ArgumentOutOfRangeException(
$"Cannot find database connection information for location '{scannerConfig.Database.Location}'");
var temp = kvMgr.GetSecret($"DatabaseCredentials--{dbConnection.Location}--Password");
var connString = String.IsNullOrEmpty(dbConnection.UserID) || String.IsNullOrEmpty(temp)
? dbConnection.ConnectionString
: $"{dbConnection.ConnectionString}; User ID={dbConnection.UserID}; Password={temp}";
this.UseSqlServer(connString,
optionsBuilder =>
optionsBuilder.MigrationsAssembly(typeof(FitchTrustContext).GetTypeInfo().Assembly.GetName()
.Name));
}
}
Run Code Online (Sandbox Code Playgroud)
不用说,虽然这为我提供了很大的灵活性(我只需更改单个配置参数就可以从本地数据库切换到云数据库,并且任何所需的密码都相当安全地存储在云中),但它可能会导致附加 -如果代码中存在错误(例如,配置文件名称错误),则使用迁移命令行开关。
为了调试此类问题,我经常不得不通过诊断 WriteLine 调用将消息输出到 Visual Studio 输出窗口。这让我觉得非常原始(更不用说耗时)。
有没有办法将调试器附加到由 add-migration 调用的代码中,以便我可以单步执行它、检查值等?我尝试在代码中插入 Launch() 调试器行,但它不起作用。这似乎让我陷入了添加管理器代码库,我没有加载任何符号,并且我尝试在代码中设置的断点显示为空的红色圆圈:它们永远不会被击中。
非常欢迎您的想法和建议!
| 归档时间: |
|
| 查看次数: |
2891 次 |
| 最近记录: |