2011-10-05 12 views
6

Al ejecutar scripts en SQL Server Management Studio, a menudo se generan mensajes que se muestran en la ventana de mensajes. Por ejemplo, al ejecutar una copia de seguridad de una base de datos:C# Controlar en SQL Server Mensaje de salida

10 por ciento procesado.

20 por ciento procesado.

Etc ...

Procesado 1722608 páginas de la base de datos 'muestra', el archivo 'Sampe' en el archivo 1.

100 por ciento procesado.

procesados ​​1 páginas para 'Sample' base de datos, archivo 'Sample_Log' en el archivo procesan 1.

BACKUP DATABASE con éxito 1722609 páginas en 202.985 segundo (66.299 MB/seg).

Me gustaría poder mostrar estos mensajes en una aplicación C# que ejecuta secuencias de comandos SQL en una base de datos. Sin embargo, no puedo entender cómo manejar el mensaje de salida de SQL a medida que se genera. ¿Alguien sabe cómo hacer esto? No me importa qué marco de conexión tengo que usar. Estoy relativamente cómodo con LINQ, NHibernate, Entity Framework, ADO.Net, Enterprise Library, y estoy feliz de aprender otros nuevos.

Respuesta

6

Aquí está el código de ejemplo que probé y funciona para mí. http://www.dotnetcurry.com/ShowArticle.aspx?ID=344

Nota el código que necesita en realidad es esta parte:

cn.Open(); 
cn.InfoMessage += delegate(object sender, SqlInfoMessageEventArgs e) 
{          
     txtMessages.Text += "\n" + e.Message;         
}; 

Es la e.Message se sigue presentando el mensaje de nuevo a txtMessages (Puede sustituir como cuadro de texto o etiqueta).

También puede hacer referencia a este artículo: Backup SQL Server Database with progress

Un ejemplo de mi código es el siguiente:

//The idea of the following code is to display the progress on a progressbar using the value returning from the SQL Server message. 
//When done, it will show the final message on the textbox. 
String connectionString = "Data Source=server;Integrated Security=SSPI;"; 
SqlConnection sqlConnection = new SqlConnection(connectionString); 

public void DatabaseWork(SqlConnection con) 
{ 
    con.FireInfoMessageEventOnUserErrors = true; 
    //con.InfoMessage += OnInfoMessage; 
    con.Open(); 
    con.InfoMessage += delegate(object sender, SqlInfoMessageEventArgs e) 
    { 
     //Use textBox due to textBox has Invoke function. You can also utilize other way. 
     this.textBox.Invoke(
      (MethodInvoker)delegate() 
      { 
       int num1; 
       //Get the message from e.Message index 0 to the length of first ' ' 
       bool res = int.TryParse(e.Message.Substring(0, e.Message.IndexOf(' ')), out num1); 

       //If the substring can convert to integer 
       if (res) 
       { 
        //keep updating progressbar 
        this.progressBar.Value = int.Parse(e.Message.Substring(0, e.Message.IndexOf(' '))); 
       } 
       else 
       { 
        //Check status from message 
        int succ; 
        succ = textBox.Text.IndexOf("successfully"); 
        //or succ = e.Message.IndexOf("successfully"); //get result from e.Message directly 
        if (succ != -1) //If IndexOf find nothing, it will return -1 
        { 
         progressBar.Value = 100; 
         MessageBox.Show("Done!"); 
        } 
        else 
        { 
         progressBar.Value = 0; 
         MessageBox.Show("Error, backup failed!"); 
        } 
       } 
      } 
     ); 
    }; 
    using (var cmd = new SqlCommand(string.Format(
     "Your SQL Script"//, 
     //QuoteIdentifier(databaseName), 
     //QuoteString(Filename)//, 
     //QuoteString(backupDescription), 
     //QuoteString(backupName) 
     ), con)) 
    { 
     //Set timeout = 1200 seconds (equal 20 minutes, you can set smaller value for shoter time out. 
     cmd.CommandTimeout = 1200; 
     cmd.ExecuteNonQuery(); 
    } 
    con.Close(); 
    //con.InfoMessage -= OnInfoMessage; 
    con.FireInfoMessageEventOnUserErrors = false; 
} 

Con el fin de conseguir el funcionamiento de progressbar, es necesario implementar esto con una backgroundworker, que su aplicación no se congelará y se realizará al 100% de repente.

Cuestiones relacionadas