SMO恢复事件永不触发

时间:2018-07-13 19:26:14

标签: c# sql-server console-application smo

我们有这个脚本化的还原过程,我正在尝试为完成的百分比添加一些日志记录,因此我们对一些长期运行的备份进入该过程有一个想法

我在还原处理程序中的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");
        }
    }

0 个答案:

没有答案