当 EF 迁移不通过程序时.cs在程序中配置依赖项(例如日志记录.cs



我会尽量解释我的情况,我希望这是有意义的。

我的项目是一个 .NET 核心 Web API。使用一个单独的类库项目,其中包含包括我的 DbContext 内容在内的模型。

问题#1我希望能够从启动中登录到控制台.cs

原因:我目前正在调试从环境变量设置变量。我想输出已设置为控制台的内容。

示例:如何从启动中写入日志.cs

现在,解决方案是将 ILoggerFactory 添加到 Program 中的服务容器中.cs如下所示:

var host = new WebHostBuilder()
.UseKestrel()
.ConfigureServices(s => {
s.AddSingleton<IFormatter, LowercaseFormatter>();
})
.ConfigureLogging(f => f.AddConsole(LogLevel.Debug))
.UseStartup<Startup>()
.Build();
host.Run();

接下来,更改 Startup.cs 构造函数以接收将从我们刚刚注册的容器中获取的 ILoggerFactory。如下:

public class Startup {
ILogger _logger;
IFormatter _formatter;
public Startup(ILoggerFactory loggerFactory, IFormatter formatter){
_logger = loggerFactory.CreateLogger<Startup>();
_formatter = formatter;
}
public void ConfigureServices(IServiceCollection services)  {
_logger.LogDebug($"Total Services Initially: {services.Count}");
// register services
//services.AddSingleton<IFoo, Foo>();
}
public void Configure(IApplicationBuilder app, IFormatter formatter) {
// note: can request IFormatter here as well as via constructor
_logger.LogDebug("Configure() started...");
app.Run(async (context) => await context.Response.WriteAsync(_formatter.Format("Hi!")));
_logger.LogDebug("Configure() complete.");
}

这解决了我的问题 - 我可以运行该应用程序,它现在可以正常工作,在我需要的地方记录。

然而。

然后当我尝试运行dotnet ef数据库更新时--startup-project=myAPIProject

它现在失败了,因为 EF 不通过 Program.cs,而是尝试直接实例化我的 Startup 类。而且由于现在我的构造函数需要一个 ILoggerFactory,EF 不知道该怎么做并抛出异常。

有谁知道解决这个问题的方法?

好的,所以我找到了一个解决方案。

而不是将 ILoggerFactory 传递给 Startup.cs 构造函数。按如下方式传递 ILogger:

private ILogger<Startup> _logger;
public Startup(IHostingEnvironment env, ILogger<Startup> logger) {
_env = env;
_logger = logger;
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
_configuration = builder.Build();
}

我的程序.cs如下所示:

var host = new WebHostBuilder() 
.UseKestrel()
.UseConfiguration(config)
.ConfigureServices(s => s.AddSingleton<IConfigurationRoot>(config))
.ConfigureLogging(f => {
f.AddConsole()
.AddDebug();
})
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();

这是因为我们的启动构造函数通过 DI 容器传递 ILogger(即使通过 EF 迁移运行并且我们尚未配置记录器(。

我在阅读后想通了这一点:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/startup(在"启动中可用的服务"下(。

现在。。。我在使用 .NET core 时遇到了很多令人沮丧的问题。我猜可能是因为它仍处于起步阶段,最佳实践等的文档仍在改进。因为我读过的大多数指南都没有这样做。

我觉得这也部分是因为 .NET core 中向"约定重于配置"的转变 - 这显然有缺点。使用强类型语言(如 C#(的好处在于,你可以让编译器在运行时之前帮助你识别此类问题。

(请记住,ILoggerFactory 一切正常,直到您使用无法访问 Program.cs 中添加服务的 EF 运行迁移(

渴望听到人们对此的看法。我相信其他人一定也经历过同样的挫折。不要误会我的意思,我喜欢 .NET core,但是在这个应用程序的开发过程中,有很多次我被困在像这样最简单的愚蠢问题上几个小时(有时更长(,这些问题本可以花在编写代码上。

相关内容