Chu*_*ell 6 c# sql-server backup smo restore
我试图使用SMO编写一个简单的实用程序来备份/恢复数据库.当备份文件中只有一个时间点时,这非常有效.但是,当存在定义了多个备份点的备份文件(而不是备份集)时,SMO总是选择最早的,而SSMS将始终选择最新的备份.
这导致数据的恢复不正确,我想弄清楚是否有一个我可以设置的属性会强制Restore类始终使用最新的备份点.
我已经尝试设置Restore.ToPointInTime但由于数据库的恢复模型很简单,因此无法正常工作.
我找到了一篇描述如何选择恢复时间的MSDN文章,其中包括将数据库设置为完全恢复模式:
http://technet.microsoft.com/en-us/library/ms179451(v=sql.105).aspx
这在使用SMO时是否必要,是否有办法使用纯SMO(没有C#sql命令)?我已经使用了Restore.ReadBackupHeaders,从中我可以及时提取可用的备份点,但无法设置要在任何地方恢复的备份点.
编辑:
这是我正在使用的代码,包括最近尝试通过smo设置数据库恢复模型的更改:
public void RestoreDatabase(string databaseName, string backupPath)
{
var server = new Server(GetServerConnection());
//If the database doesn't exist, create it so that we have something
//to overwrite.
if (!server.Databases.Contains(databaseName))
{
var database = new Database(server, databaseName);
database.Create();
}
var targetDatabase = server.Databases[databaseName];
targetDatabase.RecoveryModel = RecoveryModel.Full;
targetDatabase.Alter();
Restore restore = new Restore();
var backupDeviceItem = new BackupDeviceItem(backupPath, DeviceType.File);
restore.Devices.Add(backupDeviceItem);
restore.Database = databaseName;
restore.ReplaceDatabase = true;
restore.Action = RestoreActionType.Database;
var fileList = restore.ReadFileList(server);
var dataFile = new RelocateFile();
string mdf = fileList.Rows[0][1].ToString();
dataFile.LogicalFileName = fileList.Rows[0][0].ToString();
dataFile.PhysicalFileName = server.Databases[databaseName].FileGroups[0].Files[0].FileName;
var logFile = new RelocateFile();
string ldf = fileList.Rows[1][1].ToString();
logFile.LogicalFileName = fileList.Rows[1][0].ToString();
logFile.PhysicalFileName = server.Databases[databaseName].LogFiles[0].FileName;
restore.RelocateFiles.Add(dataFile);
restore.RelocateFiles.Add(logFile);
var backupHeaderInfo = GetBackupHeaderInformation(restore, server);
var latestBackupDate = backupHeaderInfo.Max(backupInfo => backupInfo.BackupStartDate);
restore.ToPointInTime = latestBackupDate.ToString();
server.KillAllProcesses(databaseName);
restore.SqlRestore(server);
}
Run Code Online (Sandbox Code Playgroud)
似乎这应该做的伎俩,不过线
targetDatabase.RecoveryModel = RecoveryModel.Full
Run Code Online (Sandbox Code Playgroud)
似乎没有做任何事情来改变恢复模型,导致我仍然得到以下异常:
使用SIMPLE恢复模型的数据库不支持STOPAT选项.RESTORE DATABASE异常终止.
编辑2:
我添加了这条线
targetDatabase.Alter();
Run Code Online (Sandbox Code Playgroud)
它修复了不更新的问题.但它现在恢复但使数据库处于还原模式,因此无法查询.
编辑3:
我通过将Restore.FileNumber属性设置为BackupHeaders中位置的最大值来获得代码,这似乎可以解决问题,但我仍然不确定为什么备份文件有多个备份头,但只有一个备份集.
工作代码如下.
public void RestoreDatabase(string databaseName, string backupPath)
{
var server = new Server(GetServerConnection());
//If the database doesn't exist, create it so that we have something
//to overwrite.
if (!server.Databases.Contains(databaseName))
{
var database = new Database(server, databaseName);
database.Create();
}
var targetDatabase = server.Databases[databaseName];
targetDatabase.RecoveryModel = RecoveryModel.Full;
targetDatabase.Alter();
Restore restore = new Restore();
var backupDeviceItem = new BackupDeviceItem(backupPath, DeviceType.File);
restore.Devices.Add(backupDeviceItem);
restore.Database = databaseName;
restore.ReplaceDatabase = true;
restore.NoRecovery = false;
restore.Action = RestoreActionType.Database;
var fileList = restore.ReadFileList(server);
var dataFile = new RelocateFile();
dataFile.LogicalFileName = fileList.Rows[0][0].ToString();
dataFile.PhysicalFileName = server.Databases[databaseName].FileGroups[0].Files[0].FileName;
var logFile = new RelocateFile();
logFile.LogicalFileName = fileList.Rows[1][0].ToString();
logFile.PhysicalFileName = server.Databases[databaseName].LogFiles[0].FileName;
restore.RelocateFiles.Add(dataFile);
restore.RelocateFiles.Add(logFile);
var backupHeaderInfo = GetBackupHeaderInformation(restore, server);
restore.FileNumber = backupHeaderInfo.Where(backupInfo => backupInfo.BackupType == BackupType.Database).Max(backupInfo => backupInfo.Position);
server.KillAllProcesses(databaseName);
restore.SqlRestore(server);
targetDatabase.SetOnline();
}
Run Code Online (Sandbox Code Playgroud)
尽管你说你没有多个备份集,但我认为你做到了.从备份集表的文档:
备份集包含来自单个成功备份操作的备份.
因此,如果您在单个备份文件中有"多个还原点",则您有多个备份集.通过查询msdb中的dbo.backupset表来验证这一点
除了Pedantry,我认为你正在寻找Restore对象上的FileNumber属性.这对应FILE = n于T-SQL restore命令中的备份集选项.为了得到最后一行,只需从ReadBackupHeaders调用中拉出最后一行.
要自己测试,请通过SSMS执行恢复的动作,然后点击"ok",点击顶部附近的"脚本"按钮.我怀疑你会FILE = <some number>在某处找到一个.