可滚动的服务器端游标。例如,可以使用存储过程,在运行服务器端SQL处理时这是非常高效的。还可以通过服务器端只进游标用DataReader检索数据,然后用Command对象分别进行更新。但是,经常有比使用可更新的服务器端游标更高效的修改数据的方式。
在一个N层环境中,服务器端可滚动游标的问题之一在于,它们需要在服务器上保持状态。因此,如果应用程序在中间层使用服务器端可滚动游标,客户端层就需要维持与可滚动游标所在的业务层的连接。这样,在同样使用可滚动游标的客户端应用程序屏幕存在期间,业务对象都需要保留。各种文档中已经很好地记录了这些可伸缩性问题,但是,在一些情况下服务器端游标还是很有价值的,如需要只进流水游标的情况。例如,在应用程序需要注重数据并发性问题的时候就要用到服务器端游标。使用传统的ADO,Recordset可以用一个动态游标打开,这种游标使Recordset能够获悉所有其他用户进行的插入、更改和删除操作。这种服务器端游标对于其他用户所做的更改非常敏感,可以在应用程序出现并发性问题的时候用于采取主动措施。例如,传统ADO中的动态游标经常用于这样的场合:应用程序准备在数据库中保存更改,但是又需要确保首先知道是否有其他人更改了同一条记录。当用户更改动态Recordset中一个记录值的时候,该值将自动在服务器端动态Recordset中更新:
'-- Dynamic Cursor in ASP and ADO
Set oRs.ActiveConnection = oCn
oRs.LockType = adLockOptimistic
oRs.CursorType = adOpenDynamic
oRs.CursorLocation = adUseServer
oRs.Open sSQL
服务器端游标与并发性
并发性问题在许多企业级应用程序中是合理而且常见的问题,但是使用服务器端游标以解决这一问题的代价却可能非常之高。那么在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 S
在一个N层环境中,服务器端可滚动游标的问题之一在于,它们需要在服务器上保持状态。因此,如果应用程序在中间层使用服务器端可滚动游标,客户端层就需要维持与可滚动游标所在的业务层的连接。这样,在同样使用可滚动游标的客户端应用程序屏幕存在期间,业务对象都需要保留。各种文档中已经很好地记录了这些可伸缩性问题,但是,在一些情况下服务器端游标还是很有价值的,如需要只进流水游标的情况。例如,在应用程序需要注重数据并发性问题的时候就要用到服务器端游标。使用传统的ADO,Recordset可以用一个动态游标打开,这种游标使Recordset能够获悉所有其他用户进行的插入、更改和删除操作。这种服务器端游标对于其他用户所做的更改非常敏感,可以在应用程序出现并发性问题的时候用于采取主动措施。例如,传统ADO中的动态游标经常用于这样的场合:应用程序准备在数据库中保存更改,但是又需要确保首先知道是否有其他人更改了同一条记录。当用户更改动态Recordset中一个记录值的时候,该值将自动在服务器端动态Recordset中更新:
'-- Dynamic Cursor in ASP and ADO
Set oRs.ActiveConnection = oCn
oRs.LockType = adLockOptimistic
oRs.CursorType = adOpenDynamic
oRs.CursorLocation = adUseServer
oRs.Open sSQL
服务器端游标与并发性
并发性问题在许多企业级应用程序中是合理而且常见的问题,但是使用服务器端游标以解决这一问题的代价却可能非常之高。那么在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 S
| 对此文章发表了评论 |

