使用C# SMO库恢复SQL Server备份为新库时逻辑文件报错如何解决
报错根因
Logical file 'mydbnew_log' is not part of database 'mydbnew'. Use RESTORE FILELISTONLY to list the logical file names.
RESTORE DATABASE is terminating abnormally.
触发该错误的核心问题是你对RelocateFile类的LogicalFileName属性赋值错误:
- 备份文件
mydbbackup.bak中存储的逻辑文件名是原始数据库mydb的逻辑名,和恢复后的新库名mydbnew无绑定关系 - 你直接用新库名拼接
_data/_log作为逻辑名,在备份文件中不存在,因此恢复流程中断
修复方案
有两种实现方式:
方式1:硬编码原库逻辑名
先执行SQL查询备份文件的逻辑文件名:
RESTORE FILELISTONLY FROM DISK = 'c:\temp\mydbbackup.bak'
查询结果的LogicalName列就是你需要填入的正确值,通常原库mydb的逻辑名是mydb_data(数据文件)和mydb_log(日志文件),直接替换你代码里对应的逻辑名即可。
方式2:代码自动读取备份文件逻辑名(推荐)
无需提前查询逻辑名,代码自动从备份文件读取,适配任意备份文件:
public void RestoreDatabase() { string databaseName = "mydbnew"; string userName = "user"; string password = "password"; string serverName = "(local)\\SQLEXPRESS"; string sourcePath = @"c:\temp\"; string fileName = $"mydbbackup.bak"; string backupFullPath = Path.Combine(sourcePath, fileName); ServerConnection connection = new ServerConnection(serverName, userName, password); Server sqlServer = new Server(connection); BackupDeviceItem deviceItem = new BackupDeviceItem(backupFullPath, DeviceType.File); Restore restore = new Restore(); restore.Database = databaseName; restore.ReplaceDatabase = true; restore.NoRecovery = false; restore.Devices.Add(deviceItem); // 自动读取备份文件中的逻辑文件名 DataTable fileList = restore.ReadFileList(sqlServer); foreach (DataRow row in fileList.Rows) { string logicalName = row["LogicalName"].ToString(); string physicalExtension = row["Type"].ToString() == "D" ? ".mdf" : ".ldf"; RelocateFile relocateFile = new RelocateFile( logicalName, Path.Combine(sqlServer.DefaultFile, $"{databaseName}{physicalExtension}") ); restore.RelocateFiles.Add(relocateFile); } restore.SqlRestore(sqlServer); restore.Devices.Remove(deviceItem); }
注:代码中用
sqlServer.DefaultFile获取SQL Server默认数据存储路径,避免物理文件写入权限问题,你也可以自定义路径。
内容的提问来源于stack exchange,提问作者Tonyc
相关产品推荐
相关产品推荐

