科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件ADO.NET的开发场景及传统ADO的处理

ADO.NET的开发场景及传统ADO的处理

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

当转为使用ADO.NET时,您将需要了解如何应对以前知道用ADO处理而现在必须用ADO.NET解决的场景

作者:John Papa 来源:MSDN开发精选 2007年11月13日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
服务器端游标与并发性

  并发性问题在许多企业级应用程序中是合理而且常见的问题,但是使用服务器端游标以解决这一问题的代价却可能非常之高。那么在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;
}
             图2 捕获ADO.NET中的并发性问题

  在图2 的代码中,可以注意到一个示例方法,它接收一个DataSet参数,并将DataSet中的更改通过DataAdapter的Update方法提交给数据库。如果检测到并发性问题,将由一个特定的catch代码块引发和捕获DBConcurrencyException异常。此时,事务可以回滚,然后还可重新引发异常,直到最终异常被客户端应用程序捕获,从而得以通知用户并询问用户希望如何处理。这里同样要仔细地考虑catch代码块的顺序。例如,如果首先出现一般性的catch代码块,那么它已经捕获了并发性问题。异常处理的关键在于,要确保针对更特定异常的catch代码块在其他catch代码块之前出现,从而可由特定catch代码块首先捕获特定异常。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章