ADO.NET的开发场景及传统ADO的处理
并发性问题在许多企业级应用程序中是合理而且常见的问题,但是使用服务器端游标以解决这一问题的代价却可能非常之高。那么在ADO.NET中有什么替代方式处理并发性问题呢?常见的技术是允许应用程序对数据库提交更改,然后在遇到并发性问题时引发特殊类型的异常。有一个特殊类型的异常名为DBConcurrencyException,它是从Exception基类派生而来的。因为DataSet将每列的原始值和拟更改值存储到一行中,它知道如何将值与数据库进行比较以自动寻找并发性问题。例如,假定用户将firstname字段的值由Lloyd更改为Lamar,并将更改提交给数据库,存储在DataSet中的更改将通过DataAdapter的Update方法传递给数据库。在数据真正保存之前,如果数据库中的名字不再是Lloyd,现在变成了Lorenzo,将会引发一个DBConcurrencyException异常。此异常可以以最适合应用程序需要的任何方式进行捕获和处理,例如,可以采取“最后者优先”的规则,使用户可以选择取消更改、改写或者强制更新或其他技术。
public DataSet SaveData(DataSet oDs)

...{
string sMethodName = "[public void SaveData(DataSet oDs)]";
//==========================================================
//-- Establish local variables
//==========================================================
string sProcName;
string sConnString = "Server=(local);Database=Northwind;Integrated
Security=SSPI";
SqlDataAdapter oDa = new SqlDataAdapter();
SqlTransaction oTrn = null;
SqlConnection oCn = null;
SqlCommand oInsCmd = null;
SqlCommand oUpdCmd = null;
SqlCommand oDelCmd = null;
try

...{
//==========================================================
//-- Set up the Connection
//==========================================================
oCn = new SqlConnection(sConnString);
//==========================================================
//-- Open the Connection and create the Transaction
//==========================================================
oCn.Open();
oTrn = oCn.BeginTransaction();
//==========================================================
//-- Set up the INSERT Command
//==========================================================
sProcName = "prInsert_Order";
oInsCmd = new SqlCommand(sProcName, oCn, oTrn);
oInsCmd.CommandType = CommandType.StoredProcedure;
oInsCmd.Parameters.Add(new SqlParameter("@sCustomerID",
SqlDbType.NChar, 5, "CustomerID"));
oInsCmd.Parameters.Add(new SqlParameter("@dtOrderDate",
SqlDbType.DateTime, 8,"OrderDate"));
oInsCmd.Parameters.Add(new SqlParameter("@sShipCity",
SqlDbType.NVarChar, 30, "ShipCity"));
oInsCmd.Parameters.Add(new SqlParameter("@sShipCountry",
SqlDbType.NVarChar, 30, "ShipCountry"));
oDa.InsertCommand = oInsCmd;
//==========================================================
//-- Set up the UPDATE Command
//==========================================================
sProcName = "prUpdate_Order";
oUpdCmd = new SqlCommand(sProcName, oCn, oTrn);
oUpdCmd.CommandType = CommandType.StoredProcedure;
oUpdCmd.Parameters.Add(new SqlParameter("@nOrderID",
SqlDbType.Int, 4, "OrderID"));
oUpdCmd.Parameters.Add(new SqlParameter("@dtOrderDate",
SqlDbType.DateTime, 8,"OrderDate"));
oUpdCmd.Parameters.Add(new SqlParameter("@sShipCity",
SqlDbType.NVarChar, 30, "ShipCity"));
oUpdCmd.Parameters.Add(new SqlParameter("@sShipCountry",
SqlDbType.NVarChar, 30, "ShipCountry"));
oDa.UpdateCommand = oUpdCmd;
//==========================================================
//-- Set up the DELETE Command
//==========================================================
sProcName = "prDelete_Order";
oDelCmd = new SqlCommand(sProcName, oCn, oTrn);
oDelCmd.CommandType = CommandType.StoredProcedure;
oDelCmd.Parameters.Add(new SqlParameter("@nOrderID", SqlDbType.Int, 4, "OrderID"));
oDa.DeleteCommand = oDelCmd;
//==========================================================
//-- Save all changes to the database
//==========================================================
oDa.Update(oDs.Tables["Orders"]);
oTrn.Commit();
oCn.Close();
}
catch (DBConcurrencyException exDBConcurrency)

...{
//=======================================================
//-- Roll back the transaction
//=======================================================
oTrn.Rollback();
//--------------------------------------------------------
//-- May want to rethrow the Exception at this point.
//-- This depends on how you want to handle the concurrency
//-- issue.
//--------------------------------------------------------
//-- throw(exDBConcurrency);
}
catch (Exception ex)

...{
//==========================================================
//-- Roll back the transaction
//==========================================================
oTrn.Rollback();
//--------------------------------------------------------
//-- Rethrow the Exception
//--------------------------------------------------------
throw;
}
finally

...{
oInsCmd.Dispose();
oUpdCmd.Dispose();
oDelCmd.Dispose();
oDa.Dispose();
oTrn.Dispose();
oCn.Dispose();
}
oCn.Close();
return oDs;
}