2022年DataSet的数据并发异常处理 .pdf





《2022年DataSet的数据并发异常处理 .pdf》由会员分享,可在线阅读,更多相关《2022年DataSet的数据并发异常处理 .pdf(8页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、DataSet 的数据并发异常处理ADO.NET为提高数据密集型(data-intensive)应用 程序 的性能、简化这类程序的建立过程提供了多种技术。数据集(DataSet )作为 ADO.NET对象模型的标志,作为一个微型的、不连接(disconnected)的数据源的副本提供服务。虽然使用数据集通过减少对数据库服务器 的高花费的访问而提高了性能,但是它也带来了多个用户试图同时访问相同数据的可能性,由此引起数据并发性异常(data concurrency exception)。本文调查了数据并发性异常背后的通常起因,介绍了解决这些问题的技术。把数据访问层升级到ADO.NET有很多好处,其
2、中之一是使用内部数据集对象。数据集对象基本上是一个不连接的、内存 中的数据库的拷贝。数据集对象包含一个或者多个数据表(DataTable),每个数据表一般对应于数据库中的一个表。数据集提供了很多好处,但也带来一些问题,特别是可能遇到与数据并发性异常相关的问题。我建立了一个简单的Windows Forms顾客服务应用程序,用它来解释该问题的潜在的缺陷。本文我将介绍该应用程序并演示怎样解决它所引起的数据并发性问题。本文建立的顾客服务应用程序示例是使用Visual Basic .NET和 SQL Server 2000建立的,但是由于微软 .NET 框架组件是语言无关(language-agnost
3、ic)的,因此任何与.NET 框架组件兼容的语言都可以使用。同样,由于数据集对象抽象了数据源,数据源的实际执行并不重要;无论下层的数据源是SQL Server、本地 XML 文件或者从一个服务中检索到的数据,数据并发性异常同样会出现。数据集的利弊数据集提供了很多好处,例如比起数据库层次,它强化了内存中的完整性规则。数据集对象可以定义和强化表之间的关系和列的约束,确保使用的商业规则对数据库没有缺陷。通过数据库抽象,你能建立单个代码集合访问数据集对象而不必考虑填充该数据集的源数据。下层的数据源也许是 SQL Server、Oracle甚至 XML 文件。无论下层数据源是什么,代码使用相同的方法与数
4、据集交互。这使你能改变下层数据源而不改变代码。但是使用数据集的最大好处是提高了性能。因为数据集与下层数据库断开,代码将更少作数据库的调用,显著地提高了性能。你能向数据集的多个数据表中添加新行、验证每行的有效性和参照完整性。数据适配器(DataAdapter)把数据集连接到下层数据库,能使用一条命令更新下层数据库。每个表中的所有新行都使用命令加入,以确保所有添加到数据库的行都是有效的。性能的最优化是有代价的。因为数据集对象与下层数据库断开,经常有机会出现数据没有超期(out of date)的情况。因为数据集不保存活动数据,只保存当时填充数据集的活动数据的一个快照,与数据并发性相关的问题就会出现
5、。数据并发性问题出现在多个用户访问相同的数据并且任何一个用户没有其它用户的信息就能更新数据。这就出现了一个用户偶然更新数据而不知道那些数据已经改变了,不是他在程序中看到的了。幸运的是数据集对象拥有捕获数据并发性问题的内建(built-in )支持,因此应用程序能正确地作出反应。示例程序一个虚拟的公司使用该顾客服务应用程序建立顾客订单,更新顾客的个人信息。有很多客户销售代表(CSR )在桌面上使用该应用程序。CSR使用电话获取订单,从顾客那儿收集个人信息和支付信息。顾客记录保存在数据库中以提高回头客处理订单的速度,CSR 接着建立一个订单并把产品项添加上去,指定数量和目前的价格,所有的信息收集后
6、,CSR 点击 Place Order按钮,向数据库中插入顾客和订单记录。CSR 也使用应用程序执行通过电子或者缓慢的邮件发送给公司的请求。这些请求在CSR 间均匀分开, 在每天早晨发送给他们,CSR 通过电话执行那些请求。系统设计要提高请求的实现速度,所有的顾客在CSR 之间共享。 顾客的每个请求,无论通过电话或者邮件,都被不同的CSR 处理,增加了发生数据并发性问题的机会。为了提高性能,应用程序在内存中保持了一个用顾客和订单信息填充的数据集对象。因为很多雇员同时使用该应用程序,就会有许多活动数据的不连接的快照,它们都在雇员的工作站上。所有顾客的维护、订单输入和订单维护都使用名为dsAllD
7、ata的数据集对象。图1 是建立 dsAllData的代码,它是全局模块的一部分,因此应用程序中的所有窗体都能使用它。Const connString = server=localhost;database=northwind;uid=sa;pwd= Public connCustSvc As SqlClient.SqlConnection Public daCustomer As SqlClient.SqlDataAdapter 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1
8、页,共 8 页 - - - - - - - - - Public cbCustomer As SqlClient.SqlCommandBuilder Public daOrders As SqlClient.SqlDataAdapter Public cbOrders As SqlClient.SqlCommandBuilder Public daOrderDetail As SqlClient.SqlDataAdapter Public cbOrderDetail As SqlClient.SqlCommandBuilder Public dsAllData As DataSet Publi
9、c Sub Main() connCustSvc = New SqlClient.SqlConnection(connString) daCustomer = New SqlClient.SqlDataAdapter(SELECT * FROM Customer, connCustSvc) cbCustomer = New SqlClient.SqlCommandBuilder(daCustomer) daOrders = New SqlClient.SqlDataAdapter(SELECT * FROM Orders, connCustSvc) cbOrders = New SqlClie
10、nt.SqlCommandBuilder(daOrders) daOrderDetail = New SqlClient.SqlDataAdapter(SELECT * FROM OrderDetail, connCustSvc) cbOrderDetail = New SqlClient.SqlCommandBuilder(daOrderDetail) dsAllData = New DataSet() daCustomer.MissingSchemaAction = MissingSchemaAction.AddWithKey daCustomer.Fill(dsAllData, Cust
11、omer) daOrders.MissingSchemaAction = MissingSchemaAction.AddWithKey daOrders.Fill(dsAllData, Orders) dsAllData.Tables(Orders).Columns(Total).DefaultValue = 0 daOrderDetail.MissingSchemaAction = MissingSchemaAction.AddWithKey daOrderDetail.Fill(dsAllData, OrderDetail) Application.Run(New frmCustomerM
12、aintenance() End Sub 图 1.填充数据集对象建立 dsAllData的代码建立了一个空的数据集对象、三个数据适配器(DataAdapter)和三个命令构造器(CommandBuilder)。每个数据适配器在适当的表上执行一个简单的SELECT *操作,而命令构造器用需要的剩余信息填充数据集,使它有插入 (insert ) 、 更新( update ) 和删除(delete )的能力。主程序使用数据适配器对象和所有三个表中的数据填充dsAllData ,接着使用Customer Maintenance窗体开始应用程序。图 2 显示的是Customer Maintenance屏
13、幕,它有一个绑定到dsAllData的 Customers数据表的DataGrid对象。这个简单的表格允许CSR 编辑顾客的任意基本属性。因为该表格绑定到了Customers数据表,表格中的任何改变都将自动存储到数据表中。dsAllData将保存这些值,直到CSR点击 Save Changes按钮明确地告诉窗体更新下层数据源为止。图 2. Customer Maintenance表格允许编辑名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 8 页 - - - - - - -
14、 - - 为了输入订单,使用图3 中的代码建立了几个新行并添加到dsAllData中。首先建立一个Order 记录,接着在数据表OrderDetail中为订单的每个项建立几个记录。当所有必须的行添加到dsAllData后,一个适当的数据适配器的Update方法调用将用新行更新下层数据源。Private Sub CreateOrder() Dim dr As DataRow dr = dsAllData.Tables(Orders).NewRow With dr .Item(DateOrdered) = Now .Item(CustomerID) = 1 .Item(ShipToAddress)
15、 = 123 Main .Item(ShipToCity) = Kansas City .Item(ShipToState) = MO .Item(ShipToZip) = 12345 End With dsAllData.Tables(Orders).Rows.Add(dr) AddOrderDetail(dr.Item(ID), 1, 1, 9.99) AddOrderDetail(dr.Item(ID), 2, 2, 4.99) daOrders.Update(dsAllData.Tables(Orders) daOrderDetail.Update(dsAllData.Tables(O
16、rderDetail) End Sub Private Sub AddOrderDetail(ByVal OrderID As Integer, _ ByVal ProductID As Integer, ByVal Quantity As Integer, _ ByVal Price As Single) Dim dr As DataRow dr = dsAllData.Tables(OrderDetail).NewRow With dr .Item(OrderID) = OrderID .Item(ProductID) = ProductID .Item(Quantity) = Quant
17、ity .Item(Price) = Price End With dsAllData.Tables(OrderDetail).Rows.Add(dr) End Sub 图 3.有细节记录的新订单因为 CSR 同时使用应用程序和更新顾客信息,因此好像任何时候一个CSR 看到的都是过期的信息。为了防止这种现象,应用程序的设计师决定 dsAllData的数据缓存要每隔30 分钟刷新一次,以确保CSR 通常看到正确信息。应用程序设计得很仔细,以确保数据刷新只在空闲时段进行,这样它才不影响性能。数据集刷新因此会比30 分钟长一点,这依赖于CSR 的行为。名师资料总结 - - -精品资料欢迎下载 - -
18、 - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 8 页 - - - - - - - - - 图 4.应用程序数据模型该应用程序的数据模型很简单(图4)。它使用SQL Server 2000存储,只包含三个表,顾客表、订单表、每个订单的细节表,并定义了适当的主键和关系以确保参照的完整性。此外,在 OrderDetail上定义了一个触发器来更新Orders 表的 Total 列。 每次插入、 更新或者删除一个OrderDetail记录,调用触发器计算该订单的最后销售值,并更新Orders 表的适当的行。图5 是 trg_U
19、pdateOrderTotal触发器的代码:CREATE TRIGGER trg_UpdateOrderTotal ON dbo.OrderDetail FOR INSERT, UPDATE, DELETE AS DECLARE OrderID int SELECT OrderID=OrderID FROM Inserted IF OrderID IS NULL SELECT OrderID=OrderID FROM Deleted UPDATE Orders SET Total= ( SELECT Sum(Price*Quantity) FROM OrderDetail WHERE Orde
20、rID=OrderID ) WHERE ID=OrderID 图 5.更新 Total 列第一个数据并发性异常该顾客服务应用程序使用了几个月没有任何问题,但是突然产生了一个没有处理的异常DBConcurrencyException。本段我将解释导致该异常的环境。第一个使用该应用程序的顾客销售服务人员Joe 打开应用程序。这将初始化将数据载入数据集dsAllData并按每 30 分钟一次的周期来刷新数据。 Joe 的收件箱中有一堆文件,包括顾客传真 、邮寄或者通过电子邮件发送的更改请求。他开始处理更改请求,但是经常被电话订单中断。其间,第二个客户销售服务人员Sally 到达办公室并打开了她的应用
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年DataSet的数据并发异常处理 2022 DataSet 数据 并发 异常 处理

限制150内