Entity framework core 调试EF核心添加迁移调用的代码

Entity framework core 调试EF核心添加迁移调用的代码,entity-framework-core,entity-framework-core-migrations,Entity Framework Core,Entity Framework Core Migrations,我在一个单独的程序集中定义了一个实体框架核心数据库,使用IDesignTimeDbContextFactory模式(即,我定义了一个从IDesignTimeDbContextFactory派生的类,该类有一个名为CreateDbContext的方法,该方法返回数据库上下文的实例) 由于EF Core数据库所属的应用程序使用AutoFac依赖项注入,因此IDesignTimeDbContextFactory工厂类在其构造函数中创建AutoFac容器,然后解析DbContextOptionsBuil

我在一个单独的程序集中定义了一个实体框架核心数据库,使用IDesignTimeDbContextFactory模式(即,我定义了一个从IDesignTimeDbContextFactory派生的类,该类有一个名为CreateDbContext的方法,该方法返回数据库上下文的实例)

由于EF Core数据库所属的应用程序使用AutoFac依赖项注入,因此IDesignTimeDbContextFactory工厂类在其构造函数中创建AutoFac容器,然后解析DbContextOptionsBuilder派生类,该类被馈送到数据库上下文的构造函数中(我这样做是为了根据配置文件设置控制是针对本地还是基于Azure的SqlServer数据库,密码存储在Azure KeyVault中):

公共类TemporaryDbContextFactory:IDesignTimeDbContextFactory
{
私有只读FitchTrustDBOptions\u dbOptions;
公共临时数据库上下文工厂()
{
//天哪,我永远不会
c、 Location.Equals(scannerConfig.Database.Location,
StringComparison.Ordinalingorecase)
?抛出新ArgumentOutOfRangeException(
$“找不到位置“{scannerConfig.database.location}”的数据库连接信息”;
var temp=kvMgr.GetSecret($“数据库凭据--{dbConnection.Location}--Password”);
var connString=String.IsNullOrEmpty(dbConnection.UserID)| | String.IsNullOrEmpty(temp)
?dbConnection.ConnectionString
:$“{dbConnection.ConnectionString};用户ID={dbConnection.UserID};密码={temp}”;
这个.UseSqlServer(connString,
选项生成器=>
optionsBuilder.MigrationsAssembly(typeof(FitchTrustContext).GetTypeInfo().Assembly.GetName()
(姓名);
}
}
不用说,虽然这为我提供了很大的灵活性(我可以通过更改单个配置参数从本地数据库切换到云数据库,并且任何必需的密码都可以合理地安全地存储在云中),但如果代码中有错误(例如,配置文件的名称错误),它可能会触发add-migration命令

为了调试这类问题,我经常不得不通过诊断WriteLine调用将消息输出到VisualStudio输出窗口。这让我觉得非常原始(更不用说耗时了)

有没有一种方法可以将调试器附加到由添加迁移调用的代码中,以便我可以单步执行、检查值等?我尝试在代码中插入一个Launch()调试器行,但它不起作用。它似乎把我扔进了addmanager代码库,我没有加载任何符号,我试图在代码中设置的断点显示为空的红色圆圈:它们永远不会被击中


非常欢迎您的想法和建议

Debugger.Launch()
添加到构造函数的开头,以启动实时调试器。这使您可以将VS附加到进程,并像平常一样对其进行调试。

这与将Debugger.Launch()放在添加迁移调用的代码中的任何其他位置有什么不同?我已经这样做了,结果是永远无法达到我在试图调试的代码中设置的断点。对不起,错过了这一段。不知道为什么它不起作用。。。尝试添加一个长线程.Sleep(),以便有时间连接到dotnet.exe(或ef.exe)
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 
        // https://stackoverflow.com/questions/47982194/suppressing-console-logging-by-azure-keyvault/48016958#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));
    }
}