concurrency-rowupdated.aspx

来自「东软内部材料(四)asp等相关的教学案例 」· ASPX 代码 · 共 324 行

ASPX
324
字号
<%@Page Language="C#"%>

<%@Import Namespace="System.Data" %>
<%@Import Namespace="System.Data.OleDb" %>

<%@ Register TagPrefix="wrox" TagName="connect" Src="..\global\connect-strings.ascx" %>

<!DOCTYPE HTML PUBLIC "-// W3C// DTD HTML 4.0 Transitional// EN">
<html><head>
<title>Managing Concurrent Updates with the RowUpdated Event</title>
<!-- #include file="..\global\style.inc" -->
</head>
<body bgcolor="#ffffff">
<span class="heading">Managing Concurrent Updates with the RowUpdated Event</span><hr />
<!--------------------------------------------------------------------------->

<%// -- insert connection string script --%>
<wrox:connect id="ctlConnectStrings" runat="server"/>

<div id="outError" runat="server">&nbsp;</div>

<b>Initial contents of the Books table:</b>
<asp:datagrid id="dgrResult1" runat="server" /><p />
<b>Contents of the Books table after editing:</b>
<asp:datagrid id="dgrResult2" runat="server" /><p />

<div id="outConcurrent" runat="server"></div><p />
<div id="outResult" runat="server"></div><p />

<b>Contents of the Errors table in a new DataSet after updating:</b>
<asp:datagrid id="dgrResult3" runat="server" /><p />

<b>Note:</b> while this page does execute the Update method of the DataSet, it does not<br />
actually change the original data. It uses a transaction that is rolled back afterwards.</br />
Otherwise, the update would prevent the code from running the next time.

<script language="C#" runat="server">

	string gstrResult;				// to hold the result messages
	string gstrConnect;				// to hold connection string
	DataSet gobjDataSet;			// to hold rows from database
	DataTable gobjErrorTable;		// to hold a list of errors
	DataSet gobjErrorDS;			// to hold the Errors table

	void Page_Load(Object sender, EventArgs e)
	{
		// get connection string from ..\global\connect-strings.ascx user control
		gstrConnect = ctlConnectStrings.OLEDBConnectionString;

		// specify the SELECT statement to extract the data
		string strSelect = "SELECT * FROM BookList WHERE ISBN LIKE '18610022%'";

		// create a new DataSet object
		gobjDataSet = new DataSet();

		// create a new Connection object using the connection string
		OleDbConnection objConnect = new OleDbConnection(gstrConnect);

		// create a new DataAdapter using the connection object and select statement
		OleDbDataAdapter objDataAdapter = new OleDbDataAdapter(strSelect, objConnect);

		try
		{
			// fill the dataset with data using the DataAdapter object
			objDataAdapter.Fill(gobjDataSet, "Books");
		}
		catch (Exception objError)
		{
			// display error details
			outError.InnerHtml = "<b>* Error while accessing data</b>.<br />"
							+ objError.Message + "<br />" + objError.Source;
			return;  //  and stop execution
		}

		// accept the changes to "fix" the current state of the DataSet contents
		gobjDataSet.AcceptChanges();

		// declare a variable to reference the Books table
		DataTable objTable = gobjDataSet.Tables["Books"];

		// display the contents of the Books table before changing data
		dgrResult1.DataSource = objTable.DefaultView;
		dgrResult1.DataBind();   // and bind (display) the data

		// now change some records in the Books table
		objTable.Rows[0].Delete();
		objTable.Rows[1]["Title"] = "Amateur Theatricals for Windows 2000";
		objTable.Rows[2].Delete();
		objTable.Rows[3].Delete();
		objTable.Rows[4]["PublicationDate"] = "01-01-2002";
		objTable.Rows.RemoveAt(5);
		// notice that using the Remove method on row 5 (rather than marking
		// it as deleted) means that the next row then becomes row 5
		objTable.Rows[5]["ISBN"] = "200000000";

		// add a new row using an array of values
		Object[] objValsArray = new Object[3];
		objValsArray[0] = "200000001";
		objValsArray[1] = "Impressionist Guide to Painting Computers";
		objValsArray[2] = "05-02-2002";
		objTable.Rows.Add(objValsArray);

		// display the contents of the Books table after changing the data
		dgrResult2.DataSource = objTable.DefaultView;
		dgrResult2.DataBind();   // and bind (display) the data

		//-------------------------------------------------------------------
		// change some values in the original table while the DataSet is holding
		// a disconnected copy of the data to force a concurrency error

		string strConcurrent = String.Empty;
		string strUpdate = String.Empty;
		int intRowsAffected;

		// need a new (separate) Connection and Command object
		OleDbConnection objnewConnect = new OleDbConnection(gstrConnect);
		OleDbCommand objnewCommand = new OleDbCommand();
		objnewCommand.Connection = objnewConnect;

		try
		{
			objnewConnect.Open();

			// modify two of the book titles to force concurrency errors
			strConcurrent += "<b>Concurrently executed</b>:<br />";
			DateTime datNow = DateTime.Now;
			string strNow = datNow.ToString("dd-M-yy \\a\\t hh:mm:ss");
			strUpdate = "UPDATE BookList SET Title = 'new Book Written on "
							+ strNow + "' WHERE ISBN = '186100222X'";
			objnewCommand.CommandText = strUpdate;
			intRowsAffected = objnewCommand.ExecuteNonQuery();
			strConcurrent += strUpdate + "<br /> ... <b>"
							+ intRowsAffected.ToString() + "</b> row(s) affected<br />";

			// edit the next line to force a concurrency error if none occurs
			strUpdate = "UPDATE BookList SET Title = 'Another Book Written on "
						+ strNow + "' WHERE ISBN = '1861002262'";
			objnewCommand.CommandText = strUpdate;
			intRowsAffected = objnewCommand.ExecuteNonQuery();
			strConcurrent += strUpdate + "<br /> ... <b>"
						+ intRowsAffected.ToString() + "</b> row(s) affected<br />";

			objnewConnect.Close();
		}
		catch (Exception objError)
		{
			// display error details
			outError.InnerHtml = "<b>* Error while updating original data</b>.<br />"
						+ objError.Message + "<br />" + objError.Source;
			return;  //  and stop execution
		}

		outConcurrent.InnerHtml = strConcurrent;

		//----------------------------------------------------------------

		// now set up event handler to react to RowUpdated event
		objDataAdapter.RowUpdated += new OleDbRowUpdatedEventHandler(OnRowUpdated);

		//----------------------------------------------------------------

		// create a new empty Table object to hold error rows
		gobjErrorTable = new DataTable("Errors");

		// define the columns for the Errors table
		gobjErrorTable.Columns.Add("Action", System.Type.GetType("System.String"));
		gobjErrorTable.Columns.Add("RowKey", System.Type.GetType("System.String"));
		gobjErrorTable.Columns.Add("ColumnName", System.Type.GetType("System.String"));
		gobjErrorTable.Columns.Add("OriginalValue", System.Type.GetType("System.String"));
		gobjErrorTable.Columns.Add("CurrentValue", System.Type.GetType("System.String"));
		gobjErrorTable.Columns.Add("DatabaseValue", System.Type.GetType("System.String"));

		// create a new empty DataSet object to hold Errors table
		gobjErrorDS = new DataSet();
		gobjErrorDS.Tables.Add(gobjErrorTable);

		//----------------------------------------------------------------

		// declare a variable to hold a Transaction object
		OleDbTransaction objTransaction = null;

		try
		{
			// create an auto-generated command builder to create the commands
			// to update, insert and delete the data
			OleDbCommandBuilder objCommandBuilder = new OleDbCommandBuilder(objDataAdapter);

			// set the update, insert and delete commands for the DataAdapter
			objDataAdapter.DeleteCommand = objCommandBuilder.GetDeleteCommand();
			objDataAdapter.InsertCommand = objCommandBuilder.GetInsertCommand();
			objDataAdapter.UpdateCommand = objCommandBuilder.GetUpdateCommand();

			// start a transaction so that we can roll back the changes
			// must do this on an open Connection object
			objConnect.Open();
			objTransaction = objConnect.BeginTransaction();

			// attach the current transaction to all the Command objects
			// must be done after setting Connection property
			objDataAdapter.DeleteCommand.Transaction = objTransaction;
			objDataAdapter.InsertCommand.Transaction = objTransaction;
			objDataAdapter.UpdateCommand.Transaction = objTransaction;

			// perform the update on the original data
			objDataAdapter.Update(gobjDataSet, "Books");
		}
		catch (Exception objError)
		{
			// rollback the transaction undoing any updates
			objTransaction.Rollback();

			// display error details
			outError.InnerHtml = "<b>* Error while updating original data</b>.<br />"
					+ objError.Message + "<br />" + objError.Source;
			return;  //  and stop execution
		}

		// to actually update the source tables just change the next line
		// to CommitTransaction() or remove the transaction altogether.
		// note that you will then have to change the SELECT statement and
		// code to be able to run the example again, or rebuild the
		// original data from the supplied SQL scripts
		objTransaction.Rollback();

		// display the results of the Update
		outResult.InnerHtml = gstrResult;

		// display the contents of the Errors table
		dgrResult3.DataSource = gobjErrorDS;
		dgrResult3.DataMember = "Errors";
		dgrResult3.DataBind();   // and bind (display) the data


	}

	//----------------------------------------------------------------

	// event handler for the RowUpdated event
	void OnRowUpdated(Object objSender, OleDbRowUpdatedEventArgs objArgs)
	{
		// see if the update was successful
		if (objArgs.RecordsAffected < 1)
		{
			// get the text description of the StatementType
			string strType = System.Enum.GetName(objArgs.StatementType.GetType(), objArgs.StatementType);

			// get the primary key of the row (the ISBN)
			string strRowKey = objArgs.Row["ISBN", DataRowVersion.Original].ToString();

			// get a reference to the original table in the DataSet
			DataTable objTable = gobjDataSet.Tables[0];

			string strColumnName;				// to hold the column name

			// iterate through the columns in the current row
			foreach (DataColumn objColumn in objTable.Columns)
			{
				// get the column name as a string
				strColumnName = objColumn.ColumnName;

				// see if this column has been modified
				if (objArgs.Row[strColumnName, DataRowVersion.Current]
								!= objArgs.Row[strColumnName, DataRowVersion.Original])
				{
					// create a new DataRow object instance in this table
					DataRow objDataRow = gobjErrorTable.NewRow();

					// and fill in the values
					objDataRow["Action"] = strType;
					objDataRow["RowKey"] = strRowKey;
					objDataRow["ColumnName"] = strColumnName;
					objDataRow["OriginalValue"] = objArgs.Row[strColumnName, DataRowVersion.Original];
					objDataRow["CurrentValue"] = objArgs.Row[strColumnName, DataRowVersion.Current];
					objDataRow["DatabaseValue"] = GetCurrentColumnValue(gstrConnect, strRowKey, strColumnName);

					// add new row to the Errors table
					gobjErrorTable.Rows.Add(objDataRow);

				}

			}

			// set the Status property of the row to skip current row update if there is an error
			// default is Continue which means an error will halt execution of following updates
			objArgs.Status = UpdateStatus.SkipCurrentRow;

		}

	}

	//----------------------------------------------------------------

	string GetCurrentColumnValue(string strConnect, string strISBN, string strColumnName)
	{
		// select the existing column value from the underlying table in the database
		string strSQL = "SELECT " + strColumnName
					+ " FROM BookList WHERE ISBN='" + strISBN + "'";
		string CurrVal = String.Empty;
		
		OleDbConnection objConnect = new OleDbConnection(strConnect);
		OleDbCommand objCommand = new OleDbCommand(strSQL, objConnect);
		try
		{
			objConnect.Open();
			// use ExecuteScalar for efficiency, it returns only one item
			// get the value direct from it and convert to a String
			CurrVal = objCommand.ExecuteScalar().ToString();
			objConnect.Close();
		}
		catch (Exception objError)
		{
			CurrVal = "*Error*";
		}

		return CurrVal;
	}

</script>

<!--------------------------------------------------------------------------->
<!-- #include file="..\global\foot.inc" -->
</body>
</html>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?