VS2022 Mac下.NET6项目EF数据库迁移因NLog.config报错失败
问题根因
EF Core执行数据库迁移时,需要先启动启动项目(即你的WebAPI项目)的宿主构建流程,从依赖注入容器中获取已配置完成的ApplicationDbContext实例。本次报错的初始触发点是宿主启动阶段加载nlog.config时抛出XML解析异常:根元素缺失,导致宿主构建完全失败,后续无法从DI容器获取DbContext实例,连锁触发DbContext创建失败的报错,迁移流程中断。
这个问题是跨Windows/macOS拷贝项目时的高频问题,和M1芯片本身没有直接关联。
解决步骤
- 校验
nlog.config文件完整性
跨系统拷贝文件时容易出现内容截断、编码损坏、文件为空的情况。直接打开WebAPI项目根目录下的nlog.config,确认文件不是空文件,XML结构完整:首行为XML声明,存在<nlog>根节点,没有异常乱码、空字节内容。如果文件损坏,直接从Windows端原项目拷贝正确的配置文件覆盖即可。 - 修正
nlog.config的文件复制属性
macOS端的Visual Studio 2022不会自动同步Windows环境下设置的文件属性,需要手动确认配置:右键点击nlog.config选择「属性」,将「复制到输出目录」设置为如果较新则复制。也可以直接编辑WebAPI项目的csproj文件,添加如下配置项:<ItemGroup> <None Update="nlog.config" CopyToOutputDirectory="PreserveNewest" /> </ItemGroup> - 调整NLog初始化逻辑增加容错
打开WebAPI项目的Program.cs,调整NLog加载代码,避免设计时构建(比如EF迁移)场景下日志配置错误直接阻断整个宿主启动流程,参考如下实现:var logger = LogManager.Setup() .LoadConfigurationFromFile("nlog.config", optional: false) .GetCurrentClassLogger(); try { var builder = WebApplication.CreateBuilder(args); // 原有服务注册、DbContext配置代码保持不变 var app = builder.Build(); // 原有中间件配置代码保持不变 app.Run(); } catch (Exception ex) { logger.Error(ex, "应用启动异常终止"); throw; } finally { LogManager.Shutdown(); } - 清理缓存后重新执行迁移
执行以下命令清理旧的编译残留文件,避免错误的缓存配置干扰流程:dotnet clean dotnet build # 执行迁移时明确指定启动项目和数据访问项目路径,避免跨项目路径识别错误 dotnet ef database update -c ApplicationDbContext -s ../MyCoreApplicationWebAPI/MyCoreApplicationWebAPI.csproj -p ./MyCoreApplication.DataAccess.csproj - 兜底方案:添加设计时DbContext工厂
如果以上操作后仍存在NLog加载阻断问题,可以在DataAccess项目中实现IDesignTimeDbContextFactory<ApplicationDbContext>,让EF迁移工具直接读取配置生成DbContext实例,绕过WebAPI宿主启动时的NLog加载逻辑,参考实现:public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext> { public ApplicationDbContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>(); var config = new ConfigurationBuilder() .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../MyCoreApplicationWebAPI")) .AddJsonFile("appsettings.json") .Build(); // 替换为你使用的数据库对应连接配置,比如MySQL、PostgreSQL等 optionsBuilder.UseSqlServer(config.GetConnectionString("DefaultConnection")); return new ApplicationDbContext(optionsBuilder.Options); } }
内容的提问来源于stack exchange,提问作者Manu Mohan
相关产品推荐
相关产品推荐

