События SMO Restore Never Fire
У нас есть этот процесс восстановления по сценарию, я пытаюсь добавить запись в журнал для процента выполненных операций, поэтому у нас есть представление о том, насколько далеко в процессе находятся некоторые из наших долгосрочных резервных копий.
Я добавил обработчик события в событие PercentCompleted в нашем обработчике восстановления, но кажется, что он никогда не срабатывает, поскольку мы вообще не получаем никакого вывода из обратного вызова
У любого есть идея, почему это не работает
public void Restore(string backupPath)
{
Logger.Log("Restoring database {0} from backup {1}", Name, backupPath);
using (var con = new SqlConnection(Server.GetConnectionString()))
{
var smoConn = new ServerConnection(con);
smoConn.StatementTimeout = 1200; // FMNET-20792. 20 minutes (default was 10 minutes)
var server = new Server(smoConn);
Logger.Log("Killing all processes in {0}", Name);
try
{
server.KillAllProcesses(Name);
}
catch (FailedOperationException e)
{
Logger.Log("Killing all processed failed with error below. Will still attemp to restore the DB");
Logger.Log(e.ToString());
}
var restore = new Restore();
restore.PercentComplete += (sender, args) =>
{
Logger.Log("Percent Complete {0,3}%", args.Percent);
};
restore.Devices.AddDevice(backupPath, DeviceType.File);
restore.Action = RestoreActionType.Database;
restore.Database = Name;
restore.ReplaceDatabase = true;
string serverDataPath = string.IsNullOrEmpty(server.DefaultFile)
? server.Information.MasterDBPath
: server.DefaultFile;
serverDataPath = Path.GetFullPath(serverDataPath);
Logger.Verbose("Server default data path: {0}", serverDataPath);
string serverLogPath = string.IsNullOrEmpty(server.DefaultLog)
? server.Information.MasterDBLogPath
: server.DefaultLog;
serverLogPath = Path.GetFullPath(serverLogPath);
Logger.Verbose("Server default log path: {0}", serverLogPath);
var files = restore.ReadFileList(server);
int dataFileIndex = 0;
int logFileIndex = 0;
foreach (DataRow row in files.Rows)
{
string logicalName = row["LogicalName"].ToString();
string type = row["Type"].ToString();
string newPhysicalPath;
if (type == "D")
{
newPhysicalPath = string.Format("{0}_Data{1}.mdf", Name,
dataFileIndex > 0 ? dataFileIndex.ToString() : string.Empty);
newPhysicalPath = Path.Combine(serverDataPath, newPhysicalPath);
dataFileIndex++;
}
else if (type == "L")
{
newPhysicalPath = string.Format("{0}_Log{1}.ldf", Name,
logFileIndex > 0 ? dataFileIndex.ToString() : string.Empty);
newPhysicalPath = Path.Combine(serverLogPath, newPhysicalPath);
logFileIndex++;
}
else
{
throw new ApplicationException("Unsupported file type: " + type);
}
var relocateFile = new RelocateFile(logicalName, newPhysicalPath);
Logger.Log("Will relocate {0} to {1}", logicalName, newPhysicalPath);
restore.RelocateFiles.Add(relocateFile);
}
restore.SqlRestore(server);
Logger.Log("Restore complete. Renaming logical files");
var db = server.Databases[Name];
foreach (FileGroup fg in db.FileGroups)
{
for (int i = 0; i < fg.Files.Count; i++)
{
string oldName = fg.Files[i].Name;
string newName = string.Format("{0}_Data{1}", Name, i > 0 ? i.ToString() : string.Empty);
if (!oldName.Equals(newName, StringComparison.InvariantCultureIgnoreCase))
{
Logger.Log("Renaming {0} to {1}", oldName, newName);
fg.Files[i].Rename(newName);
}
else
{
Logger.Log("Oldname equals newname ({0}), nothing to do", oldName);
}
}
}
for (int i = 0; i < db.LogFiles.Count; i++)
{
string oldName = db.LogFiles[i].Name;
string newName = string.Format("{0}_Log{1}", Name, i > 0 ? i.ToString() : string.Empty);
if (!oldName.Equals(newName, StringComparison.InvariantCultureIgnoreCase))
{
Logger.Log("Renaming {0} to {1}", oldName, newName);
db.LogFiles[i].Rename(newName);
}
else
{
Logger.Log("Oldname equals newname ({0}), nothing to do", oldName);
}
}
// Ensure FMAccess user exists in DB and is properly mapped
var fmAccessUser = Env.GetUser("FMAccess");
if (fmAccessUser == null)
{
throw new ApplicationException("Credentials with id=\"FMAccess\" don't exist in the specified environment file. FMAccess user is required when restoring a database.");
}
Logger.Log("Ensuring user {0} exists in the database {1}.", fmAccessUser.Login, Name);
// If a user already exists in DB we drop and re-create it because after restore the mapping to an existing SQL login will be lost anyway.
if (db.Users.Contains(fmAccessUser.Login))
{
Logger.Verbose("User already exists in DB, dropping.");
db.Users[fmAccessUser.Login].Drop();
}
Logger.Verbose("Creating user {0}", fmAccessUser.Login);
var u = new User(db, fmAccessUser.Login) { DefaultSchema = "dbo", Login = fmAccessUser.Login };
u.Create();
var dboRole = db.Roles["db_owner"];
dboRole.AddMember(fmAccessUser.Login);
Logger.Verbose("User created successfully");
}
}