C#使用Microsoft.SqlServer.Dac备份数据库Debug正常,Release报错求助
问题背景
使用以下C#代码结合Microsoft.SqlServer.Dac NuGet包实现SQL Server数据库备份为bacpac文件:
public class SqlServerBacpac { public static void Startup(ServerConfigOption option) { var connectionString = SqlClientHelper.BuildSqlConnectionString(option); var fileName = option.Database + "_" + DateTime.Now.ToString(option.Format) + ".bacpac"; var filePath = Path.Combine(option.Folder, fileName); var ds = new DacServices(connectionString); ds.ExportBacpac(filePath, option.Database); } }
代码在Debug环境运行正常,但发布为Release版本后抛出未处理异常:
Unhandled exception. System.ArgumentException: The path is empty. (Parameter 'path') at System.IO.Path.GetFullPath(String path) at System.Diagnostics.FileVersionInfo.GetVersionInfo(String fileName) at Microsoft.Data.Tools.Schema.Sql.Dac.DacOrigin.Operation.SetOperatingAssembly(Assembly assembly) at Microsoft.Data.Tools.Schema.Sql.Dac.DacOrigin.Operation..ctor(Assembly executingAssembly) at Microsoft.Data.Tools.Schema.Sql.Dac.DacOrigin..ctor(Assembly executingAssembly) at Microsoft.SqlServer.Dac.DacServices.<>c__DisplayClass77_1.<CreateExportOperation>b__1() at Microsoft.Data.Tools.Schema.Sql.Dac.OperationLogger.Capture(Action action) at Microsoft.SqlServer.Dac.DacServices.<>c__DisplayClass77_0.<CreateExportOperation>b__0(Object operation, CancellationToken token) at Microsoft.SqlServer.Dac.Operation.Microsoft.SqlServer.Dac.IOperation.Run(OperationContext context) at Microsoft.SqlServer.Dac.OperationExtension.CompositeOperation.Microsoft.SqlServer.Dac.IOperation.Run(OperationContext context) at Microsoft.SqlServer.Dac.OperationExtension.Execute(IOperation operation, DacLoggingContext loggingContext, CancellationToken cancellationToken) at Microsoft.SqlServer.Dac.DacServices.ExportBacpac(Func`1 streamGetter, String databaseName, DacExportOptions exportOptions, IEnumerable`1 tables, CancellationToken cancellationToken) at Microsoft.SqlServer.Dac.DacServices.ExportBacpac(String packageFileName, String databaseName, DacExportOptions options, IEnumerable`1 tables, Nullable`1 cancellationToken) at Microsoft.SqlServer.Dac.DacServices.ExportBacpac(String packageFileName, String databaseName, DacSchemaModelStorageType modelStorageType, IEnumerable`1 tables, Nullable`1 cancellationToken) at Microsoft.SqlServer.Dac.DacServices.ExportBacpac(String packageFileName, String databaseName, IEnumerable`1 tables, Nullable`1 cancellationToken) at SqlServerBackup.SqlServerBacpac.Startup(ServerConfigOption option) at Program.<<Main>$>g__RunOptions|0_1(ServerConfigOption opts) at CommandLine.ParserResultExtensions.WithParsed[T](ParserResult`1 result, Action`1 action) at Program.<Main>$(String[] args)
问题原因
异常根源是Microsoft.SqlServer.Dac库在Release模式下尝试获取当前执行程序集的物理文件路径时失败,常见触发场景:
- 采用单文件发布:程序被打包为单个可执行文件,运行时程序集无独立物理文件路径
- 启用代码裁剪(PublishTrimmed):优化过程中移除了程序集路径相关的元数据
- 程序集加载方式特殊:如从内存加载,导致
Assembly.Location为空
解决方案
1. 禁用单文件发布
在项目发布配置中取消勾选「单文件发布」选项,让程序集以独立文件形式部署,确保Dac库能获取到有效的程序集路径。
2. 调整项目发布配置
在项目文件(.csproj)中添加以下配置,禁用裁剪和单文件优化:
<PropertyGroup> <PublishSingleFile>false</PublishSingleFile> <PublishTrimmed>false</PublishTrimmed> <!-- 如需独立运行保留SelfContained,否则设为false --> <SelfContained>true</SelfContained> </PropertyGroup>
3. 代码中处理程序集路径
如果必须使用单文件发布,可通过以下方式手动处理程序集路径(注:部分场景下可能仍需禁用单文件):
public class SqlServerBacpac { public static void Startup(ServerConfigOption option) { var executingAssembly = Assembly.GetExecutingAssembly(); var assemblyPath = executingAssembly.Location; // 处理单文件发布时路径为空的情况 if (string.IsNullOrEmpty(assemblyPath)) { // 抛出明确提示,建议禁用单文件发布 throw new InvalidOperationException("当前发布模式为单文件,无法正常使用DacServices,请修改发布配置禁用单文件发布"); } var connectionString = SqlClientHelper.BuildSqlConnectionString(option); var fileName = $"{option.Database}_{DateTime.Now.ToString(option.Format)}.bacpac"; var filePath = Path.Combine(option.Folder, fileName); var ds = new DacServices(connectionString); ds.ExportBacpac(filePath, option.Database); } }
4. 升级NuGet包版本
将Microsoft.SqlServer.Dac包更新至最新稳定版本,新版本可能已修复Release模式下的路径获取问题。
验证方式
发布Release版本后执行备份操作,确认不再抛出空路径异常,且bacpac文件成功生成到指定目录。
内容的提问来源于stack exchange,提问作者AlbertXiaoPeng
相关产品推荐
相关产品推荐

