[ Team LiB ] |
Recipe 4.13 Updating Data Asynchronously Using Message QueuingProblemYou need to asynchronously update data on a database on system that is not always connected. SolutionYou must use message queuing and an XML DiffGram to:
The sample code contains four event handlers:
The C# code is shown in Example 4-32. Example 4-32. File: MessageQueueUpdateForm.cs// Namespaces, variables, and constants using System; using System.Configuration; using System.Windows.Forms; using System.Messaging; using System.Data; using System.Data.SqlClient; private const String CUSTOMERS_TABLE = "Customers"; private const String QUEUENAMEUPDATE = @".\Private$\adodotnetcb0413update"; private const String QUEUENAMERESULT = @".\Private$\adodotnetcb0413result"; private DataSet ds; // . . . private void MessageQueueUpdateForm_Load(object sender, System.EventArgs e) { // As a starting point, load the data directly. // Create the DataAdapter to load customers data. SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Customers", ConfigurationSettings.AppSettings["Sql_ConnectString"]); // Get the schema and data for the customers table. ds = new DataSet( ); da.FillSchema(ds, SchemaType.Source, CUSTOMERS_TABLE); da.Fill(ds, CUSTOMERS_TABLE); // Bind the default view of the customers table to the grid. dataGrid.DataSource = ds.Tables[CUSTOMERS_TABLE].DefaultView; } private void sendUpdateButton_Click(object sender, System.EventArgs e) { // Create the result queue if it does not exist. if(!MessageQueue.Exists(QUEUENAMEUPDATE)) MessageQueue.Create(QUEUENAMEUPDATE); // Create an object to access the result queue. MessageQueue mq = new MessageQueue(QUEUENAMEUPDATE); // Set the formatter for serialization of message bodies. mq.Formatter = new XmlMessageFormatter(new Type[] {typeof(DataSet)}); // Create a message containing the changes. mq.Send(ds.GetChanges( )); MessageBox.Show("Update message sent.","MessageQueue Update", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void processUpdateButton_Click(object sender, System.EventArgs e) { // Create the result queue if it does not exist. if(!MessageQueue.Exists(QUEUENAMEUPDATE)) MessageQueue.Create(QUEUENAMEUPDATE); // Create an object to access the result queue. MessageQueue mq = new MessageQueue(QUEUENAMEUPDATE); // Set the formatter for deserialization of message bodies. mq.Formatter = new XmlMessageFormatter(new Type[] {typeof(DataSet)}); // Receive a message from the query queue. System.Messaging.Message msg; try { msg = mq.Receive(new TimeSpan(0,0,1)); } catch(MessageQueueException ex) { MessageBox.Show(ex.Message, "MessageQueue Receive Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Create the DataAdapter and CommandBuilder to update. SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM " + CUSTOMERS_TABLE, ConfigurationSettings.AppSettings["Sql_ConnectString"]); SqlCommandBuilder cb = new SqlCommandBuilder(da); if (msg.BodyStream.Length > 0) { // Get the DataSet of changes from the message body. DataSet dsChanges = (DataSet)msg.Body; // Process the updates. da.Update(dsChanges, CUSTOMERS_TABLE); } // Get the updated DataSet. DataSet dsUpdate = new DataSet( ); da.Fill(dsUpdate, CUSTOMERS_TABLE); // Create the result queue if it does not exist. if(!MessageQueue.Exists(QUEUENAMERESULT)) MessageQueue.Create(QUEUENAMERESULT); // Create an object to access the result queue. mq = new MessageQueue(QUEUENAMERESULT); // Send a message with the update DataSet to the queue. mq.Send(dsUpdate); MessageBox.Show("Update processed. Refreshed DataSet sent.", "MessageQueue Process", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void receiveUpdateButton_Click(object sender, System.EventArgs e) { // Create the result queue if it does not exist. if(!MessageQueue.Exists(QUEUENAMERESULT)) MessageQueue.Create(QUEUENAMERESULT); // Create an object to access the result queue. MessageQueue mq = new MessageQueue(QUEUENAMERESULT); // Set the formatter for deserialization of message bodies. mq.Formatter = new XmlMessageFormatter(new Type[] {typeof(DataSet)}); // Receive a message from the result queue. System.Messaging.Message msg; try { msg = mq.Receive(new TimeSpan(0,0,1)); } catch(MessageQueueException ex) { MessageBox.Show("ERROR: " + ex.Message, "MessageQueue Receive", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Refresh the DataSet underlying the DataGrid. ds = (DataSet)msg.Body; dataGrid.DataSource = ds.Tables[CUSTOMERS_TABLE].DefaultView; MessageBox.Show("Retrieved and loaded refreshed data.", "MessageQueue Receive", MessageBoxButtons.OK, MessageBoxIcon.Information); } DiscussionThe discussion in Recipe 2.22 provides an overview of Message Queuing (MSMQ). For more information about DiffGrams, see Recipe 8.8. |
[ Team LiB ] |