Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

SQL Connection message event handler use

4.50/5 (3 votes)
25 Jul 2013CPOL2 min read 15.4K   1  
This article will describe about SQLConnection Message Event Handler and BackugroundWorker functionlity.

Introduction

This article will describe how to backup a database of SQL Server and how to receive status messages send by SQL Server while backup process is running. BackgroundWorker functionality are also described in this article.

Using the code

Backup is an essential object while developing a program for client. Data may be corrupt in many cases, so we have to develop a program by which we can preserve user data on external media or computer.

This article describes about how to backup an SQL Server database. You will also learn about asynchronous functionality of BackgroundWroker class in this article.

I also want to introduce about SqlConnection class property FireInfoMessageEventOnUsersErrors working in this article. When SQL Server executes an command it sends status to application which can be caught by application.

In this article when Backup processes Status of backup in percentage will be received by application which is send by SQL Server to show progress bar value and percentage on label control.

Finally, this article doesn’t use any third party library/control to perform backup action. All classes used in this code are built-in .NET Framework. You can run this code without any problem and can incorporate in any application that uses SQL Server as backend to store data. 

Source code:

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Data.Sql;
using System.Data.SqlClient;
using System.IO;
using System.Data.Common;

namespace BackupDatabase
{
    public partial class Form1 : Form
    {
        SqlConnection sCon = null;
        SqlCommand sCmd = null;
        SqlDataAdapter sAdpt = null;

        BackgroundWorker bWorker = null;
        bool bDone = true;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cboAuth.SelectedIndex = 0;
            this.Height = 235;

            setWindowLocation();
        }

        private void bttnCancel_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void bttnBrowse_Click(object sender, EventArgs e)
        {
            folderDialog.Description = "Please select path";
            folderDialog.RootFolder = Environment.SpecialFolder.Desktop;

            if (folderDialog.ShowDialog() != DialogResult.Cancel)
                txtBackupLocation.Text = folderDialog.SelectedPath;
        }

        private void bttnConnect_Click(object sender, EventArgs e)
        {
            if (txtServer.Text.Trim() == string.Empty)
            {
                MessageBox.Show("Please select Server Name", 
                  "Connect to Server", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            else if (cboAuth.SelectedIndex==1)
            {
                if (txtUserName.Text.Trim() == string.Empty)
                {
                    MessageBox.Show("Please enter User Name", 
                      "Connect to Server", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
                else if (txtPassword.Text.Trim() == string.Empty)
                {
                    MessageBox.Show("Please enter Password", 
                      "Connect to Server", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
            }

            string sConnectionString = string.Empty;

            if (cboAuth.SelectedIndex == 1)
                sConnectionString = "Data Source=" + txtServer.Text + 
                  "; User Id=" + txtUserName.Text + "; Password=" + 
                  txtPassword.Text + "; Database=Master";
            else
                sConnectionString = "Data Source=" + txtServer.Text + 
                  "; Integrated Security=SSPI; Database=Master";

            try
            {
                sCon = new SqlConnection(sConnectionString);
                sCon.Open();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Connect to Server", 
                      MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            this.Height = 423;

            setWindowLocation();

            loadDatabaseList();
        }

        void setWindowLocation()
        {
            this.Top = (Screen.PrimaryScreen.Bounds.Height - this.Height) / 2;
            this.Left = (Screen.PrimaryScreen.Bounds.Width - this.Width) / 2;
        }

        void loadDatabaseList()
        {
            sCmd = new SqlCommand("select name from sys.databases order by name", sCon);
            sAdpt = new SqlDataAdapter(sCmd);

            DataSet ds = new DataSet();
            sAdpt.Fill(ds, "tblList");

            cboDatabaseList.DisplayMember = "name";
            cboDatabaseList.DataSource = ds.Tables[0];
        }

        private void bttnStart_Click(object sender, EventArgs e)
        {
            if (cboDatabaseList.SelectedIndex == -1)
            {
                MessageBox.Show("No database name found to backup", 
                  "Connect to Server", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            else if (txtBackupLocation.Text.Trim()==string.Empty)
            {
                MessageBox.Show("No backup location found to backup", 
                  "Connect to Server", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            bWorker = new BackgroundWorker();

            bWorker.WorkerReportsProgress = true;
            bWorker.WorkerSupportsCancellation = true;

            bWorker.DoWork += new DoWorkEventHandler(bWorker_DoWork);
            bWorker.ProgressChanged += new ProgressChangedEventHandler(bWorker_ProgressChanged);
            bWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bWorker_RunWorkerCompleted);

            BackupHelper bI = new BackupHelper(sCon,cboDatabaseList.Text, txtBackupLocation.Text);
            bWorker.RunWorkerAsync(bI);
        }

        void bWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackupHelper bI = (BackupHelper)e.Argument;

            bI.StartBackup(bWorker);
        }

        void bWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            pBar.Value = 0;
            lblPercent.Text = "0 %";

            if (bDone)
            {
                MessageBox.Show("Backup Complete !", 
                  "Connect to Server", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        void bWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == -1)
            {
                bDone = false;
                bWorker.CancelAsync();
                MessageBox.Show(e.UserState.ToString(), 
                  "Connect to Server", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                pBar.Value = e.ProgressPercentage;
                lblPercent.Text = pBar.Value + " %";
            }
        }
    }

    public class BackupHelper
    {
        private SqlConnection sBackupConnection = null;
        private string sDatabaseName = null;
        private string sBackupLocation = null;

        BackgroundWorker bW = null;

        private SqlConnection BackupConnection
        {
            get
            {
                return sBackupConnection;
            }
            set
            {
                sBackupConnection = value;
            }
        }

        private string DatabaseName
        {
            get
            {
                return sDatabaseName;
            }
            set
            {
                sDatabaseName = value;
            }
        }

        private string BackupLocation
        {
            get
            {
                return sBackupLocation;
            }
            set
            {
                sBackupLocation = value;
            }
        }

        public BackupHelper()
        {

        }

        public BackupHelper(SqlConnection sBackupConnection, 
                string sDatabaseName, string sBackupLocation)
        {
            this.BackupConnection = new SqlConnection(sBackupConnection.ConnectionString);
            this.DatabaseName = sDatabaseName;
            this.BackupLocation = sBackupLocation;
        }

        public void StartBackup(BackgroundWorker bW)
        {
            this.bW = bW;

            sBackupConnection.FireInfoMessageEventOnUserErrors = true;
            sBackupConnection.InfoMessage += OnInfoMessage;
            sBackupConnection.Open();

            StringBuilder sb = new StringBuilder();

            sb.AppendFormat(@"BACKUP DATABASE [{0}] TO  DISK = N'{1}' WITH " + 
                @"DESCRIPTION = N'{2}', NOFORMAT, NOINIT, NOSKIP, REWIND, NOUNLOAD,  STATS = 1",
                this.DatabaseName, Path.Combine(this.BackupLocation, 
                this.DatabaseName + ".bak"), this.DatabaseName + " full backup");

            SqlCommand sqlCmd = new SqlCommand(sb.ToString(), sBackupConnection);
            sqlCmd.CommandTimeout = 10000;
            sqlCmd.ExecuteNonQuery();

            sBackupConnection.Close();
        }

        protected void OnInfoMessage(object sender, SqlInfoMessageEventArgs e)
        {
            if (e.Message.Contains("percent processed."))
            {
                int iPercent = 0;
                int.TryParse(e.Message.Replace("percent processed.", ""), out iPercent);

                bW.ReportProgress(iPercent, null);
            }
            else
            {
                #region COMMENT

                string CommandStatus = string.Empty;

                foreach (SqlError info in e.Errors)
                    if (info.Class > 10)
                        CommandStatus += e.Message + Environment.NewLine;

                if (CommandStatus != string.Empty)
                {
                    bW.ReportProgress(-1, CommandStatus);
                }

                #endregion
            }
        }
    }
}

This statement will confirm that the child thread can send data to it's parent thread.

C#
bWorker.WorkerReportsProgress = true;

This statement specifies that the child thread can be interrupt while running.

C#
bWorker.WorkerSupportsCancellation = true;

This statement specifies that method bWorker_DoWork will be execute when RunWorkerAsync method will be call.

C#
bWorker.DoWork += new DoWorkEventHandler(bWorker_DoWork);

This statement specifies that method bWorker_ProgressChanged will be execute when child thread call ReportProgress method.

C#
bWorker.ProgressChanged += new ProgressChangedEventHandler(bWorker_ProgressChanged);

Finally... These following lines of code will specifies the SqlConnection class can send message when any SqlCommand fires on it, and which method will be call Specifies by InfoMessage property.

C#
sBackupConnection.FireInfoMessageEventOnUserErrors = true;
sBackupConnection.InfoMessage += OnInfoMessage;

Finally, I think this article will help to improve knowledge of beginners and developers also. Thanks...

Next Update

In the next version of this article I will introduce the restore functionality. 

License

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