Exemplo n.º 1
0
        public SqlExecutionResult <string> Restore(string sourcePath, int version = 3, bool preventActionToBegin = false)
        {
            this.TraceDebug("Restauration d'un backup de base de données...");

            CreateSqlDirForDebugPurpose();

            SqlConnection sqlConn = CreateAdminSqlConnection(true);
            SqlCommand    sqlCmd;

            var task = new Task <string>(() =>
            {
                try
                {
                    // On retrouve l'emplacement de la nouvelle base
                    SqlDataReader reader;
                    sqlCmd = new SqlCommand($@"SELECT physical_name FROM sys.master_files WHERE physical_name LIKE '%\{Const.DataBaseName_v3}.mdf'", sqlConn);
                    sqlConn.Open();
                    reader = sqlCmd.ExecuteReader();
                    if (!reader.Read())
                    {
                        throw new Exception("Impossible de retrouver l'emplacement de la nouvelle base de donnée.");
                    }
                    string newDbPath = Directory.GetParent((string)reader[0]).FullName;
                    sqlConn.Close();

                    // On récupère la version de la nouvelle base
                    sqlCmd = new SqlCommand($"USE [{Const.DataBaseName_v3}]", sqlConn);
                    sqlConn.Open();
                    sqlCmd.ExecuteNonQuery();
                    sqlCmd = new SqlCommand("GetDatabaseVersion", sqlConn)
                    {
                        CommandType = System.Data.CommandType.StoredProcedure
                    };
                    reader = sqlCmd.ExecuteReader();
                    if (!reader.Read())
                    {
                        throw new Exception("Impossible de retrouver la version de la nouvelle base de donnée.");
                    }
                    Version newDbVersion = Version.Parse((string)reader[0]);
                    sqlConn.Close();

                    //On coupe toutes les connexions à la base en la passant en single user
                    sqlCmd = new SqlCommand($"ALTER DATABASE [{Const.DataBaseName_v3}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE", sqlConn);
                    sqlConn.Open();
                    sqlCmd.ExecuteNonQuery();
                    sqlConn.Close();

                    // On supprime la nouvelle base
                    var deleteText = $@"IF EXISTS(SELECT * FROM sysdatabases WHERE name='{Const.DataBaseName_v3}') DROP DATABASE [{Const.DataBaseName_v3}]";
                    sqlCmd         = new SqlCommand(deleteText, sqlConn);
                    this.TraceDebug("Suppression de la base");
                    this.TraceDebug(deleteText);
                    sqlConn.Open();
                    sqlCmd.ExecuteNonQuery();
                    sqlConn.Close();

                    // On restaure le backup dans la nouvelle instance
                    string restoreCmdText;
                    // On récupère les noms logiques du backup
                    restoreCmdText = $@"RESTORE FILELISTONLY FROM DISK=N'{sourcePath}'";
                    sqlCmd         = new SqlCommand(restoreCmdText, sqlConn);
                    this.TraceDebug("Restauration de la base (récupération des noms logiques)");
                    this.TraceDebug(restoreCmdText);
                    sqlConn.Open();
                    var dataReader        = sqlCmd.ExecuteReader();
                    string LogicalNameDb  = "";
                    string LogicalNameLog = "";
                    while (dataReader.Read())
                    {
                        string logicalName = (string)dataReader["LogicalName"];
                        string type        = (string)dataReader["Type"];
                        if (type == "D")
                        {
                            LogicalNameDb = logicalName;
                        }
                        else if (type == "L")
                        {
                            LogicalNameLog = logicalName;
                        }
                    }
                    sqlConn.Close();
                    this.TraceDebug($"Db : {LogicalNameDb}, Log : {LogicalNameLog}");
                    restoreCmdText = $@"RESTORE DATABASE [{Const.DataBaseName_v3}] FROM DISK=N'{sourcePath}' WITH MOVE '{LogicalNameDb}' TO '{newDbPath}\{Const.DataBaseName_v3}.mdf', MOVE '{LogicalNameLog}' TO '{newDbPath}\{Const.DataBaseName_v3}.LDF'";
                    sqlCmd         = new SqlCommand(restoreCmdText, sqlConn);
                    this.TraceDebug("Restauration de la base");
                    this.TraceDebug(restoreCmdText);
                    sqlConn.Open();
                    sqlCmd.ExecuteNonQuery();
                    sqlConn.Close();

                    // On effectue l'upgrade jusqu'à la version de l'installeur
                    this.TraceDebug($"Update de la base vers {newDbVersion}");
                    Scripts.GoTo(sqlConn, newDbVersion);

                    // On restore les droits utilisateurs sur la base
                    this.TraceDebug($"Restauration des droits utilisateurs");
                    Scripts.Execute(sqlConn, "RestoreUserRights");
                }
                catch (Exception e)
                {
                    this.TraceError("Erreur pendant l'execution du script sql de restauration", e);
                    throw e;
                }

                return(sourcePath);
            });

            if (!preventActionToBegin)
            {
                task.Start();
            }

            return(SqlExecutionResult.New(sqlConn, task));
        }