Files
Sdaleo/Systems/SQLServer/Database.cs

574 lines
29 KiB
C#

#if SQLSERVER
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace Sdaleo.Systems.SQLServer
{
/// <summary>
/// Specific actions for SQL Server Databases
/// </summary>
public class SQLServerDatabase
{
#region Database List
/// <summary>
/// Returns a array of any found Databases on the specified SQL Server intance
/// </summary>
/// <param name="credential">SQL Server Credentials</param>
/// <param name="DatabaseList">list of Databases if any found, or null if not</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabasesListAll(IConnectDb credential, out string[] DatabaseList)
{
DatabaseList = null;
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
// Execute the Query
string sql = "SELECT [name] FROM sys.databases";
DB db = DB.Create(credential.DBMS.WithoutDatabase());
DBRetVal retVal = db.FillDataTable(sql);
if (retVal.IsValid)
{
List<string> DataBaseNames = new List<String>();
foreach (DataRow row in retVal.GetDataTableRetVal().Rows)
DataBaseNames.Add(row["name"].ToString());
DatabaseList = DataBaseNames.ToArray();
}
return retVal;
}
/// <summary>
/// Returns a array of any found Databases that are NOT SQL Default Databases (like master, model, etc);
/// </summary>
/// <param name="credential">SQL Server Credentials</param>
/// <param name="DatabaseList">list of Databases if any found, or null if not</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabasesListNonDefault(IConnectDb credential, out string[] DatabaseList)
{
DatabaseList = null;
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
// Look for all Databases that are Non-Default
string[] DatabaseListAll = null;
DBError retVal = DatabasesListAll(credential, out DatabaseListAll);
if(!retVal.ErrorOccured && DatabaseListAll != null)
{
List<String> DatabaseListNonDefault = new List<String>();
foreach (string DatabaseName in DatabaseListAll)
{
if(!SQLServerUtilities.IsDefaultDatabaseName(DatabaseName))
DatabaseListNonDefault.Add(DatabaseName);
}
DatabaseList = DatabaseListNonDefault.ToArray();
}
return retVal;
}
#endregion
#region Alter Database
/// <summary>
/// Use this to Raise the specified Database to it's highest Compatibility Level as allowed
/// on the specified SQLServer (2005/2008/etc.)
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseRaiseCompatibility(IConnectDb credential)
{
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
// How to change compatibility level has changed in sql server 2008 (so we'll try to
// use the newer way of doing it if we can.
string sql = string.Empty;
SQLServerVersion ServerVersion;
DBError dberror = SQLServerGeneral.GetSQLServerVersion(credential, out ServerVersion);
if (dberror.ErrorOccured)
return dberror;
switch (ServerVersion)
{
case SQLServerVersion.SQL_SERVER_2008:
sql = String.Format("ALTER DATABASE [{0}] SET COMPATIBILITY_LEVEL = {1}", credential.DBMS.Database, (int)ServerVersion);
break;
default:
sql = String.Format("EXEC sp_dbcmptlevel [{0}], {1}", credential.DBMS.Database, (int)ServerVersion);
break;
}
// Execute the Query and return result
DB db = DB.Create(credential.DBMS.WithoutDatabase());
DBRetVal retVal = db.ExecuteNonQuery(sql);
return retVal;
}
/// <summary>
/// Allows the caller to set the Database into Single User Mode. This is * microsoft recommended *
/// for certain type of operations on the Database to make sure nobody else can use the DB.
/// Note: If Database is in Use * This will timeout
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseSetToSingleUserMode(IConnectDb credential)
{
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
// Execute the Query and return result
string sql = String.Format("ALTER DATABASE [{0}] SET SINGLE_USER", credential.DBMS.Database);
DB db = DB.Create(credential.DBMS.WithoutDatabase());
DBRetVal retVal = db.ExecuteNonQuery(sql);
return retVal;
}
/// <summary>
/// Allows the caller to set the Database into Multi User Mode. This should be called
/// if the caller called DatabaseSetToSingleUserMode() previously
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseSetToMultiUserMode(IConnectDb credential)
{
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
// Execute the Query and return result
string sql = String.Format("ALTER DATABASE [{0}] SET MULTI_USER", credential.DBMS.Database);
DB db = DB.Create(credential.DBMS.WithoutDatabase());
DBRetVal retVal = db.ExecuteNonQuery(sql);
return retVal;
}
/// <summary>
/// Calls DBCC SHRINKDATABASE and DBCC UPDATEUSAGE on the passed in Database
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseShrink(IConnectDb credential)
{
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
// Execute the Query and return result
DB db = DB.Create(credential.DBMS.WithoutDatabase());
string sql = String.Format("DBCC SHRINKDATABASE ([{0}])", credential.DBMS.Database);
DBRetVal retVal = db.ExecuteNonQuery(sql);
if (!retVal.ErrorOccured)
{
sql = String.Format("DBCC UPDATEUSAGE ([{0}])", credential.DBMS.Database);
retVal = db.ExecuteNonQuery(sql);
}
return retVal;
}
/// <summary>
/// Iterates all tables on the database and enables/disables all trigers for each table
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <param name="bEnable">true to enable, false to disable</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError EnableDisableAllTriggers(IConnectDb credential, bool bEnable)
{
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
// Get All Table Names from the Database
string[] TableNames = null;
DBError dberror = SQLServerTable.Tables(credential, out TableNames);
if (dberror.ErrorOccured)
return dberror;
// Execute the Query and return result
DB db = DB.Create(credential);
DBRetVal retVal = new DBRetVal();
foreach (string TableName in TableNames)
{
// Execute the Query for each Table
string sql = String.Format("ALTER TABLE [{0}] {1} TRIGGER ALL", TableName, (bEnable ? "ENABLE" : "DISABLE"));
retVal = db.ExecuteNonQuery(sql);
if (retVal.ErrorOccured)
break;
}
return retVal;
}
#endregion
#region Databae Create / Exists
/// <summary>
/// Checks to see if we can query the specified server for the Database (Existence check)
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <param name="bExists">Returns true if the Database Exists, false otherwise</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseExists(IConnectDb credential, out bool bExists)
{
bExists = false;
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
// Execute the Query and return result
string sql = String.Format("EXEC sp_helpdb @dbname = [{0}]", credential.DBMS.Database);
DB db = DB.Create(credential.DBMS.WithoutDatabase());
DBRetVal retVal = db.ExecuteNonQuery(sql);
bExists = !retVal.ErrorOccured;
return retVal;
}
/// <summary>
/// Create a new Database with the specified DatabaseName in the specified DataPath, if specified, or DefaultPath otherwise
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <param name="DataPath">Data Path to Create Database in (not required)</param>
/// <param name="TryAttachDBOnError">true to allow Attach Database when error occurs, false otherwise</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseCreate(IConnectDb credential, string DataPath, bool TryAttachDBOnError)
{
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
// if DataPath is empty, get default datapath for SQL ServerInstance
if (String.IsNullOrEmpty(DataPath))
SQLServerGeneral.SQLServerDefaultPath(credential.DBMS.WithoutDatabase(), out DataPath);
// Fill in Database FileName and Path Details
string sql = String.Format("CREATE DATABASE [{0}] ", credential.DBMS.Database);
if (!String.IsNullOrEmpty(DataPath))
sql += String.Format(@"ON (NAME = [{0}_dat], FILENAME = '{1}\{0}.dat') LOG ON (NAME = [{0}_log], FILENAME = '{1}\{0}_log.ldf')", credential.DBMS.Database, DataPath);
// Execute the Command
DB db = DB.Create(credential.DBMS.WithoutDatabase());
DBRetVal retVal = db.ExecuteNonQuery(sql);
// Upon DB Creation error, see if we could possibly attach the DB
bool bErrorOccuredThatCouldMaybeBeResolvedByAttaching = false;
if (retVal.ErrorOccured && !DBMS.GetAllErrorNumbers(DBSystem.SQL_SERVER, retVal).Contains(ErrorConst.ERROR_DB_ALREADY_EXISTS) && (
DBMS.GetAllErrorNumbers(DBSystem.SQL_SERVER, retVal).Contains(ErrorConst.ERROR_DB_SOME_FILE_NAMES_COULD_NOT_BE_CREATED) ||
DBMS.GetAllErrorNumbers(DBSystem.SQL_SERVER, retVal).Contains(ErrorConst.ERROR_DB_CAN_NOT_CREATE_FILE_BECAUSE_IT_ALREADY_EXISTS) ||
DBMS.GetAllErrorNumbers(DBSystem.SQL_SERVER, retVal).Contains(ErrorConst.ERROR_DB_THERE_ALREADY_IS_AN_OBJECT_IN_THE_DB_WITH_THIS_NAME)))
{
bErrorOccuredThatCouldMaybeBeResolvedByAttaching = true;
}
// Upon Error, and if we are allowed to attach && datapath is valid, try to attach
if (retVal.ErrorOccured && TryAttachDBOnError && bErrorOccuredThatCouldMaybeBeResolvedByAttaching && !String.IsNullOrEmpty(DataPath))
{
String[] strFileNames = new String[]
{
string.Format(@"{1}\{0}.dat", credential.DBMS.Database, DataPath),
string.Format(@"{1}\{0}_log.ldf", credential.DBMS.Database, DataPath)
};
DBError retValError = DatabaseAttach(credential, strFileNames);
return retValError;
}
return retVal;
}
#endregion
#region Database Attach / Dettach
/// <summary>
/// Attaches a Database to an SQL Server Instance
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <param name="strFileNames">Pass in the filenames when attaching Database (required)</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseAttach(IConnectDb credential, string[] strFileNames)
{
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
if ((strFileNames == null || strFileNames.Length == 0))
return DBError.Create("Invalid FileNames Passed In");
// Generate the SQL Query
string sql = String.Format("EXEC sp_attach_db @dbname = [{0}]", credential.DBMS.Database);
for (int i = 0; i < strFileNames.Length; ++i)
sql = sql + String.Format(", @filename{0:d1} = '{1}'", (i + 1), strFileNames[i]);
// Execute the Query
DB db = DB.Create(credential.DBMS.WithoutDatabase());
DBRetVal retVal = db.ExecuteNonQuery(sql);
// If Error Occured try renaming dat files to mdf * legacy code *
bool bRetryAttachingErrorOccured = false;
if (retVal.ErrorOccured &&
(DBMS.GetAllErrorNumbers(DBSystem.SQL_SERVER, retVal).Contains(ErrorConst.ERROR_DB_THERE_ALREADY_IS_AN_OBJECT_IN_THE_DB_WITH_THIS_NAME) ||
DBMS.GetAllErrorNumbers(DBSystem.SQL_SERVER, retVal).Contains(ErrorConst.ERROR_DB_DEVICE_ACTIVATION_FAILED)))
{
bRetryAttachingErrorOccured = true;
}
// Retry on Attach if failure occured &
// filenames contain .dat files & we have an attach specific error * LEGACY CODE Usuage *
if (retVal.ErrorOccured && bRetryAttachingErrorOccured)
{
bool bRetry = false;
List<string> retryArr = new List<string>();
foreach (string strFileName in strFileNames)
{
if (strFileName.Contains(".dat"))
{
strFileName.Replace(".dat", ".mdf");
bRetry = true;
}
retryArr.Add(strFileName);
}
// Only do an actually retry if .dat files were replaced
if (bRetry)
return DatabaseAttach(credential, retryArr.ToArray());
}
return retVal;
}
/// <summary>
/// Dettaches a Database from an SQL Server Instance
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseDettach(IConnectDb credential)
{
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
// Execute the Query and return result
string sql = String.Format("sp_detach_db @dbname = [{0}]", credential.DBMS.Database);
DB db = DB.Create(credential.DBMS.WithoutDatabase());
DBRetVal retVal = db.ExecuteNonQuery(sql);
return retVal;
}
#endregion
#region Database Copy
/// <summary>
/// Copies a specified Database on the specified SQLServer into a new specified Database
/// </summary>
/// <param name="credential">SQL Server Credentials with Database Info</param>
/// <param name="DatabaseNameDest">Name of Database To be copied To (required)</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseCopy(IConnectDb credential, string DatabaseNameDest)
{
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credential.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
dbError = Validation.IsValidDatabaseName(DatabaseNameDest);
if (dbError.ErrorOccured)
return dbError;
string strDefaultPath;
DBError dberror = SQLServerGeneral.SQLServerDefaultPath(credential, out strDefaultPath);
if (dberror.ErrorOccured)
return dberror;
// First Step - Backup the source database to a custom Backup file
string sql = String.Format(@"BACKUP DATABASE [{0}] TO DISK = '{1}\{0}.DB Backup' WITH INIT, NAME = '{0} Backup', PASSWORD = 'dbCopy Backup', MEDIAPASSWORD = 'XaseY 1-33', INIT , FORMAT", credential.DBMS.Database, strDefaultPath);
DB db = DB.Create(credential.DBMS.WithoutDatabase());
DBRetVal retVal = db.ExecuteNonQuery(sql);
if (retVal.ErrorOccured)
return retVal;
// Second Step - Retrieve the dat & log Logical Names for the newly backed-up Database
string strDataLogical = string.Empty;
string strLogLogical = string.Empty;
sql = String.Format(@"RESTORE FILELISTONLY FROM DISK = '{0}\{1}.DB Backup' WITH FILE = 1, PASSWORD = 'dbCopy Backup', MEDIAPASSWORD = 'XaseY 1-33'", strDefaultPath, credential.DBMS.Database);
retVal = db.FillDataTable(sql);
if (!retVal.IsValid)
return retVal;
foreach (DataRow row in retVal.GetDataTableRetVal().Rows)
{
switch (row["Type"].ToString())
{
case "D":
strDataLogical = row["LogicalName"].ToString();
break;
case "L":
strLogLogical = row["LogicalName"].ToString();
break;
}
}
if (String.IsNullOrEmpty(strDataLogical) || String.IsNullOrEmpty(strLogLogical))
return DBError.Create("DataLogical or LogLogical could not be found");
// Third Step - Restore Backup file to the new Database name
sql = String.Format(@"RESTORE DATABASE [{0}] FROM DISK = '{1}\{2}.DB Backup' WITH FILE = 1, PASSWORD = 'dbCopy Backup', MEDIAPASSWORD = 'XaseY 1-33', MOVE '{3}' TO '{1}\{0}.dat', MOVE '{4}' TO '{1}\{0}_log.ldf', RECOVERY, REPLACE", DatabaseNameDest, strDefaultPath, credential.DBMS.Database, strDataLogical, strLogLogical);
retVal = db.ExecuteNonQuery(sql);
if (retVal.ErrorOccured)
{
// try again
retVal = db.ExecuteNonQuery(sql);
if (!retVal.IsValid)
return retVal;
}
// Fourth Step - Try to Delete the Backup file (No Need to have a potentially massive data file just sitting there
// ~SQL Server blocked access to procedure 'sys.xp_cmdshell' of component 'xp_cmdshell' because this component is turned off as part of the
// security configuration for this server. A system administrator can enable the use of 'xp_cmdshell' by using sp_configure.
// For more information about enabling 'xp_cmdshell', see "Surface Area Configuration" in SQL Server Books Online
// sql = String.Format("exec master.dbo.xp_cmdshell 'del /Q /F \"{0}\\{1}.DB Backup\"'", strDefaultPath, DatabaseNameSrc);
// db.ExecuteNonQuery(sql);
// Legacy Usuage, we are leaving the Backup File behind (*leaking the file* so to speak)
return retVal;
}
/// <summary>
/// Copies a specified Database on the specified SQLServer into a new specified Database onto a different specified Instance * Must be on Same Server *
/// </summary>
/// <param name="credentialSrc">SQL Server Credentials with Database Info to be copied from (required)</param>
/// <param name="credentialDest">SQL Server Credentials with Database Info to be copied to (required)</param>
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
public static DBError DatabaseCopySepInst(IConnectDb credentialSrc, IConnectDb credentialDst)
{
DBError dbError = ValidationConsts.IsCredentialValid(credentialSrc, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credentialSrc.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
dbError = ValidationConsts.IsCredentialValid(credentialDst, DBSystem.SQL_SERVER);
if (dbError.ErrorOccured)
return dbError;
if (!credentialDst.DBMS.IsDatabaseSetAndNonSystem)
return DBError.Create("Invalid Database Passed In via Credential");
if (String.Compare(credentialSrc.DBMS.Server, credentialDst.DBMS.Server, true) != 0)
return DBError.Create("Must be on the Same Server");
if (String.Compare(credentialSrc.DBMS.Instance, credentialDst.DBMS.Instance, true) == 0)
return DBError.Create("Can not be the same Instance");
// Get Src Default Path *of the DB*
string strDefaultPathSrc;
DBError dberror = SQLServerGeneral.SQLServerDefaultPath(credentialSrc, out strDefaultPathSrc);
if (dberror.ErrorOccured)
return dberror;
// Get Dest Default Path *of the Server*
string strDefaultPathDest;
dberror = SQLServerGeneral.SQLServerDefaultPath(credentialDst, out strDefaultPathDest);
if (dberror.ErrorOccured)
return dberror;
// Make sure that both Paths aren't the same *Two instances should never have the same path!*
if (strDefaultPathSrc.ToUpper() == strDefaultPathDest.ToUpper())
return DBError.Create(String.Format("The File Path of the Source Database {0} and the Destination Database {1} on Server {1} are identical.", credentialSrc.DBMS.Database, credentialDst.DBMS.Database, credentialDst.DBMS.Server));
// Create Src N' Dest Connections * No Limit on the Command timeout *
// Could be very large database that we are trying to copy
DB dbSrc = DB.Create(credentialSrc.DBMS.WithoutDatabase().Timeouts.WithCommandTimeout(0));
DB dbDst = DB.Create(credentialDst.DBMS.WithoutDatabase().Timeouts.WithCommandTimeout(0));
// First Step - Backup the source database to a custom DB Backup file to the DESTINATION path
string sql = String.Format(@"BACKUP DATABASE [{0}] TO DISK = '{1}\{0}.DB Backup' WITH INIT, NAME = '{0} Backup', PASSWORD = 'dbCopy Backup', MEDIAPASSWORD = 'XaseY 1-33', INIT , FORMAT", credentialSrc.DBMS.Database, strDefaultPathSrc);
DBRetVal retVal = dbSrc.ExecuteNonQuery(sql);
if (retVal.ErrorOccured)
return retVal;
// Second Step - Retrieve the dat & log Logical Names for the newly backed-up Database File
string strDataLogical = string.Empty;
string strLogLogical = string.Empty;
sql = String.Format(@"RESTORE FILELISTONLY FROM DISK = '{0}\{1}.DB Backup' WITH FILE = 1, PASSWORD = 'dbCopy Backup', MEDIAPASSWORD = 'XaseY 1-33'", strDefaultPathSrc, credentialSrc.DBMS.Database);
retVal = dbSrc.FillDataTable(sql);
if (!retVal.IsValid)
return retVal;
foreach (DataRow row in retVal.GetDataTableRetVal().Rows)
{
switch (row["Type"].ToString())
{
case "D":
strDataLogical = row["LogicalName"].ToString();
break;
case "L":
strLogLogical = row["LogicalName"].ToString();
break;
}
}
if (String.IsNullOrEmpty(strDataLogical) || String.IsNullOrEmpty(strLogLogical))
return DBError.Create(String.Format("The retrieval of Logical Names for Database '{0}' failed for Server Instance '{1}' in Path '{2}'.", credentialSrc.DBMS.Database, credentialSrc.DataSource, strDefaultPathDest));
// Third Step - Restore Backup file to the new Database name onto the new (Dest) instance
sql = String.Format(@"RESTORE DATABASE [{0}] FROM DISK = '{1}\{2}.DB Backup' WITH FILE = 1, PASSWORD = 'dbCopy Backup', MEDIAPASSWORD = 'XaseY 1-33', MOVE '{3}' TO '{5}\{0}.dat', MOVE '{4}' TO '{5}\{0}_log.ldf', RECOVERY, REPLACE", credentialDst.DBMS.Database, strDefaultPathSrc, credentialSrc.DBMS.Database, strDataLogical, strLogLogical, strDefaultPathDest);
retVal = dbDst.ExecuteNonQuery(sql);
if (!retVal.ErrorOccured)
{
// try again
retVal = dbDst.ExecuteNonQuery(sql);
if (!retVal.IsValid)
return retVal;
}
// Fourth Step - Try to Delete the Backup file (No Need to have a potentially massive data file just sitting there
// ~SQL Server blocked access to procedure 'sys.xp_cmdshell' of component 'xp_cmdshell' because this component is turned off as part of the
// security configuration for this server. A system administrator can enable the use of 'xp_cmdshell' by using sp_configure.
// For more information about enabling 'xp_cmdshell', see "Surface Area Configuration" in SQL Server Books Online
// sql = String.Format("exec master.dbo.xp_cmdshell 'del /Q /F \"{0}\\{1}.DB Backup\"'", strDefaultPath, DatabaseNameSrc);
// db.RunSQLCommandTextExecuteNonQuery(sql);
// Legacy Usuage, we are leaving the Backup File behind (*leaking the file* so to speak)
return retVal;
}
#endregion
}
}
#endif