Click here to Skip to main content
15,887,175 members
Articles / Web Development / ASP.NET

ASP.NET Optimistic Concurrency Control

Rate me:
Please Sign up or sign in to vote.
4.73/5 (25 votes)
19 Aug 20039 min read 223.5K   2.3K   111  
How to implement the optimistic concurrency control without the DataSet
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace Concurrency
{
	/// <summary>
	/// Summary description for Product.
	/// </summary>
	public class Product : BasePage
	{
		protected System.Web.UI.WebControls.Label Label1;
		protected System.Web.UI.WebControls.Label Label2;
		protected System.Web.UI.WebControls.Label Label3;
		protected System.Web.UI.WebControls.Label Label4;
		protected System.Web.UI.WebControls.Label Label6;
		protected System.Web.UI.WebControls.Label Label7;
		protected System.Web.UI.WebControls.Label Label8;
		protected System.Web.UI.WebControls.TextBox txtName;
		protected System.Web.UI.WebControls.TextBox txtQtyPerUnit;
		protected System.Web.UI.WebControls.TextBox txtUnitPrice;
		protected System.Web.UI.WebControls.TextBox txtUnitsInStock;
		protected System.Web.UI.WebControls.TextBox txtUnitsOnOrder;
		protected System.Web.UI.WebControls.TextBox txtReorderLevel;
		protected System.Web.UI.WebControls.CheckBox chkDiscontinued;
		protected System.Web.UI.WebControls.Button btnAccept;
		protected System.Web.UI.WebControls.Button btnCancel;
		protected System.Web.UI.WebControls.DropDownList cmbCategories;
		protected System.Web.UI.WebControls.DropDownList cmbSuppliers;
		protected System.Web.UI.WebControls.Label lblConcurrencyMsg;
		protected System.Web.UI.WebControls.Label Label5;

		#region Web Form Designer generated code
		override protected void OnInit(EventArgs e)
		{
			//
			// CODEGEN: This call is required by the ASP.NET Web Form Designer.
			//
			InitializeComponent();
			base.OnInit(e);
		}
		
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{    
			this.btnAccept.Click += new System.EventHandler(this.btnAccept_Click);
			this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
			this.Load += new System.EventHandler(this.Page_Load);

		}
		#endregion

		#region Page Events

		private void Page_Load(object sender, System.EventArgs e)
		{
			if (! IsPostBack)
			{
				// Load the categories
				foreach (BLL.Category category in new BLL.Category().GetCategories())
					this.cmbCategories.Items.Add(new ListItem(category.Name, category.ID.ToString()));

				// Load the suppliers
				foreach (BLL.Supplier supplier in new BLL.Supplier().GetSuppliers())
					this.cmbSuppliers.Items.Add(new ListItem(supplier.Name, supplier.ID.ToString()));

				// Load the product data
				LoadProduct();
			}
		}

		/// <summary>
		/// Accepts the user changes
		/// </summary>
		private void btnAccept_Click(object sender, System.EventArgs e)
		{
			Save();
		}

		/// <summary>
		/// Cancels the product edit
		/// </summary>
		private void btnCancel_Click(object sender, System.EventArgs e)
		{
			Response.Redirect("Default.aspx");
		}

		#endregion

		/// <summary>
		/// Loads the product data based on the product ID
		/// </summary>
		private void LoadProduct()
		{
			// Get the product ID to read
			int productID = 0;
			try 
			{
				productID = Int32.Parse(Request.QueryString["ProductID"]);
			} 
			catch 
			{
				Response.Redirect("Error.aspx?msg=" + System.Web.HttpUtility.UrlEncode("The product ID is invalid."));
			}

			// Read the product's data
			BLL.Product product = new BLL.Product();
			product.ID = productID;
			if (!product.Read())
				Response.Redirect("Error.aspx?msg=" + System.Web.HttpUtility.UrlEncode("The product has been deleted by another user."));

			// Fill the form
			txtName.Text = product.Name;
			cmbCategories.Items.FindByValue(product.CategoryID.ToString()).Selected = true;
			cmbSuppliers.Items.FindByValue(product.SupplierID.ToString()).Selected = true;
			txtQtyPerUnit.Text = product.QuantityPerUnit;
			txtUnitPrice.Text = product.UnitPrice.ToString();
			txtUnitsOnOrder.Text = product.UnitsOnOrder.ToString();
			txtUnitsInStock.Text = product.UnitsInStock.ToString();
			txtReorderLevel.Text = product.ReorderLevel.ToString();
			chkDiscontinued.Checked = product.Discontinued;
			
			// Keep the original object
			SetConcurrencyObject(product);
		}
		
		/// <summary>
		/// Saves the products data
		/// </summary>
		private void Save()
		{
			// Hide the concurrency error label
			lblConcurrencyMsg.Visible = false;
			
			// Get the product ID
			int productID = Int32.Parse(Request.QueryString["ProductID"]);
			
			// Get a product instance and set the properties
			BLL.Product product = new BLL.Product(	productID,
													txtName.Text,
													Int32.Parse(cmbSuppliers.SelectedItem.Value),
													Int32.Parse(cmbCategories.SelectedItem.Value),
													txtQtyPerUnit.Text,
													decimal.Parse(txtUnitPrice.Text),
													Int32.Parse(txtUnitsInStock.Text),
													Int32.Parse(txtUnitsOnOrder.Text),
													Int32.Parse(txtReorderLevel.Text),
													chkDiscontinued.Checked
													);
			// Set the concurrency time stamp
			product.Concurrency = GetConcurrencyObject().Concurrency;
			
			try
			{
				// Update the product
				product.Update();
				
				// Redirect to the product's list
				Response.Redirect("Default.aspx");
			}
			catch (DeletedRowInaccessibleException)
			{
				Response.Redirect("Error.aspx?msg=" + System.Web.HttpUtility.UrlEncode("The product has been deleted by another user."));
			}
			catch (DBConcurrencyException)
			{
				ConcurrencyException();
			}
			catch (Exception ex)
			{
				throw ex;
			}				
		}

		/// <summary>
		/// Processes the concurrency exception
		/// </summary>
		private void ConcurrencyException()
		{
			// Get the mapping controls - object properties 
			Hashtable controls = GetControlsMap();
			
			// Update the page to show the fields that have concurrency conflicts
			ShowConcurrencyFields(controls);
			
			// Show the concurrency error label
			lblConcurrencyMsg.Visible = true;
		}

		/// <summary>
		/// Gets the controls mapped to the object's properties
		/// </summary>
		/// <returns>Control mapping</returns>
		private Hashtable GetControlsMap()
		{	
			// Map the properties to the controls
			Hashtable controls = new Hashtable();
			controls.Add("Name", this.txtName);
			controls.Add("CategoryID", this.cmbCategories);
			controls.Add("SupplierID", this.cmbSuppliers);
			controls.Add("QuantityPerUnit", this.txtQtyPerUnit);
			controls.Add("UnitPrice", this.txtUnitPrice);
			controls.Add("UnitsInStock", this.txtUnitsInStock);
			controls.Add("UnitsOnOrder", this.txtUnitsOnOrder);
			controls.Add("ReorderLevel", this.txtReorderLevel);
			controls.Add("Discontinued", this.chkDiscontinued);

			return controls;
		}

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Teo
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions