Click here to Skip to main content
Click here to Skip to main content

Using SMO for Backup, Restore and Security Purposes

By , 29 Aug 2007
 

Introduction

Finally, I have decided to post my first article here. So I expect some feedback from you.

Thank you in advance!

I will try to explain the ways in which you can use Server Management Objects to perform some administrative tasks with SQL Server 2005 using C#.

I use some of this code for automation of the deployment of our projects. And may be I will post another article on this subject (Deployment Automation).

The Code

I will list the methods with some brief explanation. I am not pretending about Best Practices in Code Design.

To use this code you must have references to the following assemblies:

  • Microsoft.SqlServer.ConnectionInfo
  • Microsoft.SqlServer.Smo
  • Microsoft.SqlServer.SmoEnum
  • Microsoft.SqlServer.SqlEnum

I use a method GetServer(). This method creates an instance of SMO.Server object so I can use it to perform some operations on that SQL Server 2005.

private static Server GetServer()
{
ServerConnection conn = new ServerConnection(serverName, userName, password);
Server myServer = new Server(conn);
return myServer;
}

BackupDatabase method with the relevant event handlers:

static void BackupDataBase(string databaseName, string destinationPath)
{
WriteToLogAndConsole("Backup the {0} database!", databaseName);
Server myServer = GetServer();
Backup backup = new Backup();
backup.Action = BackupActionType.Database;
backup.Database = databaseName;
destinationPath = System.IO.Path.Combine(destinationPath, databaseName + ".bak");
backup.Devices.Add(new BackupDeviceItem(destinationPath, DeviceType.File));
backup.Initialize = true;
backup.Checksum = true;
backup.ContinueAfterError = true;
backup.Incremental = false;
backup.LogTruncation = BackupTruncateLogType.Truncate;
backup.PercentComplete += new PercentCompleteEventHandler(backup_PercentComplete);
backup.Complete += 
    new Microsoft.SqlServer.Management.Common.ServerMessageEventHandler
    (backup_Complete);
// Perform backup.
backup.SqlBackup(myServer);
}

//The event handlers
static void backup_Complete
    (object sender, Microsoft.SqlServer.Management.Common.ServerMessageEventArgs e)
{
WriteToLogAndConsole(e.ToString() + "% Complete");
}
static void backup_PercentComplete(object sender, PercentCompleteEventArgs e)
{
WriteToLogAndConsole(e.Percent.ToString() + "% Complete");
}
//NOTE: WriteToLogAndCosole is some method for logging I have implemented 

RestoreDatabase() method with the relevant event handlers:

static void RestoreDataBase(string BackupFilePath, 
            string destinationDatabaseName, 
            string DatabaseFolder, 
            string DatabaseFileName,
            string DatabaseLogFileName)
{
Server myServer = GetServer();
Restore myRestore = new Restore();
myRestore.Database = destinationDatabaseName;
Database currentDb = myServer.Databases[destinationDatabaseName];
if (currentDb != null)
    myServer.KillAllProcesses(destinationDatabaseName);
myRestore.Devices.AddDevice(BackupFilePath, DeviceType.File);
string DataFileLocation = DatabaseFolder + "\\" + destinationDatabaseName + ".mdf";
string LogFileLocation = DatabaseFolder + "\\" + destinationDatabaseName + "_log.ldf";
myRestore.RelocateFiles.Add(new RelocateFile(DatabaseFileName, DataFileLocation));
myRestore.RelocateFiles.Add(new RelocateFile(DatabaseLogFileName, LogFileLocation));
myRestore.ReplaceDatabase = true;
myRestore.PercentCompleteNotification = 10;
myRestore.PercentComplete += 
    new PercentCompleteEventHandler(myRestore_PercentComplete);
myRestore.Complete += new ServerMessageEventHandler(myRestore_Complete);
WriteToLogAndConsole("Restoring:{0}", destinationDatabaseName);
myRestore.SqlRestore(myServer);
currentDb = myServer.Databases[destinationDatabaseName];
currentDb.SetOnline();
}
static void myRestore_Complete
    (object sender, Microsoft.SqlServer.Management.Common.ServerMessageEventArgs e)
{
WriteToLogAndConsole(e.ToString() + " Complete");
}
static void myRestore_PercentComplete(object sender, PercentCompleteEventArgs e)
{
WriteToLogAndConsole(e.Percent.ToString() + "% Complete");
} 

CreateLogin() Method

static void CreateLogin
    (string sqlLoginName,string sqlLoginPassword,string databaseName)
{
myServer=GetServer()
Login newLogin = myServer.Logins[sqlLogin];
if (newLogin != null)
    newLogin.Drop();
newLogin = new Login(myServer, sqlLogin);
newLogin.PasswordPolicyEnforced = false;
newLogin.LoginType = LoginType.SqlLogin;
newLogin.Create(sqlLoginPassword);
//Create DatabaseUser
DatabaseMapping mapping = 
    new DatabaseMapping(newLogin.Name, MainDbName, newLogin.Name);
Database currentDb = myServer.Databases[databaseName];
User dbUser = new User(currentDb, newLogin.Name);
dbUser.Login = sqlLogin;
dbUser.Create();
dbUser.AddToRole("db_owner");
}

Conclusion

Again, this is my first article. So I am sorry for the poor formatting and explanations. I just wanted to show you some of the code you can use with SMO and that's it. I will appreciate any feedback.

Expect more from me SOON!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

niki_mbr
Web Developer
Bulgaria Bulgaria
Member
4+ Years in Software Design and Development.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionGetting error in login creationmembermaushmi15 May '13 - 22:40 
Why did you create a Database Mapping,what purpose it solves in Login Creation.I am using the same code but failing at Create method call with following error.
Exception calling "Create" with "0" argument(s): "Create failed for User 'MyNewLogin'. "
At C:\Users\maushmi.kumari\Desktop\ps\CreateDBUser.ps1:64 char:17
+ $dbUser.Create <<<< ();
+ CategoryInfo : NotSpecified: (Smile | :) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
AnswerRe: Getting error in login creationmemberniki_mbr15 May '13 - 22:58 
Have you enabled SQL authentication?
Nikolay Yordanov,
 
Senior Developer - MCSD.NET, MCAD.NET, MCDBA

QuestionBackup Progress Problemmemberjia yu20 Aug '09 - 21:25 
Hi Niki,
Thank you for your code first.
I used the backup code in my program, but I found the Complete event was triggered and the PercentComplete event didn't been triggered.
Could you tell me the reason? Or what wrong with my code?
Thank you again! Big Grin | :-D
 
There is my code:

private void BackupDataBase(Project proj)
        {
            Backup backup = new Backup();
            backup.Action = BackupActionType.Database;
            backup.Database = proj.InitialCatalog.Tag.ToString();
            backup.Incremental = false;
            backup.Initialize = true;
            backup.LogTruncation = BackupTruncateLogType.Truncate;
 
            BackupDeviceItem backupItemDevice = 
              new BackupDeviceItem(proj.BackupFilePath, DeviceType.File);
            backup.Devices.Add(backupItemDevice);
            backup.PercentCompleteNotification = 1;
            backup.PercentComplete += new PercentCompleteEventHandler(ProgressChanged);
            backup.Complete += new ServerMessageEventHandler(ProgressCompleted);
 
            ServerConnection srvconn = new ServerConnection();
            srvconn.ConnectionString = proj.ConnectionString;
            Server srv = new Server(srvconn);
            backup.SqlBackupAsync(srv);
        }
 
        private void ProgressChanged(object sender,PercentCompleteEventArgs e)
        {
            if (this.InvokeRequired)
            {
                deleProgressChanged dele = new deleProgressChanged(ProgressChanged);
                this.BeginInvoke(dele,sender,e);
            }
            else
            {
                PrgRunning.Value = e.Percent;  //PrgRunning is a ProgressBar          
            }
            
        }
 
        private void ProgressCompleted(object sender,ServerMessageEventArgs e)
        {
            if (this.InvokeRequired)
            {
                deleProgressCompleted dele = new deleProgressCompleted(ProgressCompleted);
                this.BeginInvoke(dele,sender,e);
            }
            else
            {
                ChangeState(false);
                MessageBox.Show("Backup Completed!","Infomation",MessageBoxButtons.OK,MessageBoxIcon.Information);
            }
        }
    }

AnswerRe: Backup Progress Problemmemberniki_mbr20 Aug '09 - 22:03 
Try to change the backup.PercentCompleteNotification to 10.
http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.management.smo.backuprestorebase.percentcompletenotification.aspx[^]
Remarks
 
For the default value 10, PercentCompleteEventHandler is called for every 10 percent of the task completed. The event handler might report slightly later if the backup or restore procedure does not release the process to the event handler immediately after the event is raised.
 
Nikolay Yordanov,
 
Senior Developer - MCSD.NET, MCAD.NET, MCDBA

GeneralRe: Backup Progress Problemmemberjia yu21 Aug '09 - 4:30 
Hi Niki,
With SQL SERVER 2000, I changed the PercentCompleteNotification property to 10 and 20, but the problem was the same. And when connected to the SQLEXPRESS within the VS.NET 2008 to backup, the program didn't stop.
Are there any other reasons?
Thanks for your reply!
GeneralRe: Backup Progress Problemmemberniki_mbr21 Aug '09 - 18:10 
I can only confirm that this works in SQL Server 2005. I guess that it should work with SQL 2008 (may be with some modification and referencing the new Smo asseblies) And I guess that it should not give the expected results in SQL Server 2000.
 
Nikolay Yordanov,
 
Senior Developer - MCSD.NET, MCAD.NET, MCDBA

AnswerRe: Backup Progress Problemmemberpfxp23 Aug '09 - 3:14 
Hi jia yu,
 
I had a similar problem when backing up three databases when using SMO with SQL Server 2008 Express. Sometimes I would get the PercentComplete event notifications and sometimes
I would not. I suspect it has to do with running SQL Server Management Studio Express at the same time as your application.
 
Maybe we need to detect if there are other connections to the database, put the database into SINGLE_USER mode, do our backup and then return the database to MULTI_USER mode.
 
Just a thought...
Peter
GeneralTanksmemberh_r_sh6 Apr '09 - 2:48 
Method KillAllProcesses() was help me. Thank again.
Generalsmomemberppro24 Nov '08 - 7:21 
what versions of sql express sp2 are compatible with smo? I am running 9.0.3042.00, dose not it seem to recognize the references to smo.
P
GeneralThanks!memberChris Khoo23 Mar '07 - 18:11 
Hi
 
Thanks very much for the article - it's helped me a lot!
 
Cheers
 
Chris

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 29 Aug 2007
Article Copyright 2006 by niki_mbr
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid