ADO.NET 中的数据并发
当多个用户试图同时修改数据时,需要建立控制机制来防止一个用户的修改对同时操作的其他用户所作的修改产生不利的影响。处理这种情况的系统叫做“并发控制”。
并发控制的类型
通常,管理数据库中的并发有三种常见的方法:
?保守式并发控制 - 在从获取记录直到记录在数据库中更新的这段时间内,该行对用户不可用。
?开放式并发控制 - 只有当实际更新数据时,该行才对其他用户不可用。更新将在数据库中检查该行并确定是否进行了任何更改。如果试图更新已更改的记录,则将导致并发冲突。
?最后的更新生效 - 只有当实际更新数据时,该行才对其他用户不可用。但是,不会将更新与初始记录进行比较;而只是写出记录,这可能就改写了自上次刷新记录后其他用户所进行的更改。
保守式并发
保守式并发通常用于两个目的。第一,在某些情况下,存在对相同记录的大量争用。在数据上放置锁所费的成本小于发生并发冲突时回滚更改所费的成本。
在事务过程中不宜更改记录的情况下,保守式并发也非常有用。库存应用程序便是一个很好的示例。假定有一个公司代表正在为一名潜在的客户检查库存。您通常要锁定记录,直到生成订单为止,这通常会将该项标记为“已订购”状态并将其从可用库存中移除。如果未生成订单,则将释放该锁,以便其他检查库存的用户得到准确的可用库存计数。
但是,在断开的结构中无法进行保守式并发控制。连接打开的时间只够读取数据或更新数据,因此不能长时间地保持锁。此外,长时间保留锁的应用程序将无法进行伸缩。
注意 如果基础数据源支持事务,则可以通过在事务中更新数据来模拟保守式并发。有关更多信息,请参见 ADO.NET 中的事务。
开放式并发
在开放式并发中,只有在访问数据库时才设置并保持锁。这些锁将防止其他用户在同一时间更新记录。除了进行更新这一确切的时刻之外,数据始终可用。有关更多信息,请参见开放式并发。
当试图更新时,已更改行的初始版本将与数据库中的现有行进行比较。如果两者不同,更新将失败,并引发并发错误。这时,将由您使用所创建的业务逻辑来协调这两行。
最后的更新生效
当使用“最后的更新生效”时,不会对初始数据进行检查,而只是将更新写入数据库。很明显,可能会发生以下情况:
?用户 A 从数据库获取一项记录。
?用户 B 从数据库获取相同的记录,对其进行修改,然后将更新后的记录写回数据库。
?用户 A 修改“旧”记录并将其写回数据库。
在上述情况中,用户 A 永远也不会看到用户 B 作出的更改。如果您计划使用并发控制的“最后的更新生效”方法,则要确保这种情况是可以接受的。
ADO.NET 和 Visual Studio .NET 中的并发控制
因为数据结构基于断开的数据,所以 ADO.NET 和 Visual Studio .NET 使用开放式并发。因此,您需要添加业务逻辑,以利用开放式并发解决问题。
如果您选择使用开放式并发,则可以通过两种常规的方法来确定是否已发生更改:版本方法(实际版本号或日期时间戳)和保存所有值方法。
版本号方法
在版本号方法中,要更新的记录必须具有一个包含日期时间戳或版本号的列。当读取该记录时,日期时间戳或版本号将保存在客户端。然后,将对该值进行部分更新。
处理并发的一种方法是仅当 WHERE 子句中的值与记录上的值匹配时才进行更新。该方法的 SQL 表示形式为:
UPDATE Table1 SET Column1 = @newvalue1, Column2 = @newvalue2
WHERE DateTimeStamp = @origDateTimeStamp或者,可以使用版本号进行比较:
UPDATE Table1 SET Column1 = @newvalue1, Column2 = @newvalue2
WHERE RowVersion = @origRowVersionValue如果日期时间戳或版本号匹配,则表明数据存储区中的记录未被更改,并且可以安全地使用数据集中的新值对该记录进行更新。如果不匹配,则将返回错误。您可以编写代码,在 Visual Studio .NET 中实现这种形式的并发检查。您还必须编写代码来响应任何更新冲突。为了确保日期时间戳或版本号的准确性,您需要在表上设置触发器,以便在发生对行的更改时,对日期时间戳或版本号进行更新。
保存所有值方法
使用日期时间戳或版本号的替代方法是在读取记录时获取所有字段的副本。ADO.NET 中的 DataSet 对象维护每个修改记录的两个版本:初始版本(最初从数据源中读取的版本)和修改版本(表示用户更新)。当试图将记录写回数据源时,数据行中的初始值将与数据源中的记录进行比较。如果它们匹配,则表明数据库记录在被读取后尚未经过更改。在这种情况下,数据集中已更改的值将成功地写入数据库。
对于数据适配器的四个命令(DELETE、INSERT、SELECT 和 UPDATE)来说,每个命令都有一个参数集合。每个命令都有用于初始值和当前值(或修改值)的参数。
注意 由于不存在初始记录,添加新记录(INSERT 命令)只需要当前值;移除记录(DELETE 命令)只需要使用初始值来定位要删除的记录。
以下示例显示一个数据集命令的命令文本,该命令更新一个典型的客户表。该命令是为动态 SQL 和开放式并发而指定的。UPDATE Customers SET CustomerID = @currCustomerID, CompanyName = @currCompanyName, ContactName = @currContactName,
ContactTitle = currContactTitle, Address = @currAddress, City = @currCity,
PostalCode = @currPostalCode, Phone = @currPhone, Fax = @currFax
WHERE (CustomerID = @origCustomerID) AND (Address = @origAddress OR @origAddress IS NULL AND Address IS NULL) AND (City = @origCity OR @origCity IS NULL AND City IS NULL)
AND (CompanyName = @origCompanyName OR @origCompanyName IS NULL AND CompanyName IS NULL) AND (ContactName = @origContactName OR @origContactName IS NULL AND ContactName IS NULL) AND (ContactTitle = @origContactTitle OR @origContactTitle IS NULL AND ContactTitle IS NULL)
AND (Fax = @origFax OR @origFax IS NULL AND Fax IS NULL) AND (Phone = @origPhone OR @origPhone IS NULL AND Phone IS NULL) AND (PostalCode = @origPostalCode OR @origPostalCode IS NULL AND PostalCode IS NULL);
SELECT CustomerID, CompanyName, ContactName, ContactTitle, Address, City,
PostalCode, Phone, Fax
FROM Customers WHERE (CustomerID = @currCustomerID)
复制代码请注意,九个 SET 语句参数表示将写入数据库的当前值,而九个 WHERE 语句参数则表示用于定位初始记录的初始值。
前九个 SET 语句参数对应于参数集合中的前九个参数。这些参数会将其 SourceVersion 属性设置为 Current。
接着的九个 WHERE 语句参数用于开放式并发。这些占位符对应于参数集合中接着的九个参数,这些参数的每一个都将其 SourceVersion 属性设置为 Original。
SELECT 语句用于在发生更新后刷新数据集。它是您在“高级 SQL 生成选项”对话框中设置“刷新数据集”选项时生成的。
注意 上面的 SQL 使用命名参数,而 OleDbDataAdapter 命令则使用问号 (?) 作为参数占位符。
默认情况下,如果您在“数据适配器配置向导”中选择“开放式并发”选项,Visual Studio 将为您创建这些参数。此时将由您根据自己的业务要求来添加错误处理代码。ADO.NET 提供了一个 DBConcurrencyException 对象,它返回违反并发规则的行。有关更多信息,请参见处理并发错误。
摘自:http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/vbcon/html/vbtskPerformingOptimisticConcurrencyChecking.asp
ADO.NET 中的数据并发的更多相关文章
- ado.net中,数据的批量处理
//btBigImport按钮点击事件 private void btBigImport_Click(object sender, RoutedEventArgs e) { //连接字符 ...
- ADO.NET 中的新增功能
ADO.NET 中的新增功能: .NET Framework (current version) 以下是 .NET Framework 4.5 中 ADO.NET 的新增功能. SqlClient D ...
- Oracle的数据并发与一致性详解(下)
上篇介绍了数据并发与一致性的相关概念.以及oracle的事务隔离级别等内容,本篇继续介绍锁机制.自动锁.手动锁.用户自定义锁的相关内容. 请尊重作者劳动成果,转载请标明原文链接: https://ww ...
- [翻译]比较ADO.NET中的不同数据访问技术(Performance Comparison:Data Access Techniques)
Performance Comparison: Data Access Techniques Priya DhawanMicrosoft Developer Network January 2002 ...
- Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)
jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...
- 第18课-数据库开发及ado.net 连接数据库.增.删.改向表中插入数据并且返回自动编号.SQLDataReade读取数据
第18课-数据库开发及ado.net 连接数据库.增.删.改向表中插入数据并且返回自动编号.SQLDataReade读取数据 ADO.NET 为什么要学习? 我们要搭建一个平台(Web/Winform ...
- ADO.NET中DataSet、DataTable、DataRow的数据复制方法
DataSet 对象是支持 ADO.NET的断开式.分布式数据方案的核心对象 ,用途非常广泛.我们很多时候需要使用其中的数据,比如取得一个DataTable的数据或者复制另一个DataTabe中的数据 ...
- 【ADO.NET】3、从TXT中导入数据到数据库
数据库字段与类型id int,Name nvarchar(20),Age int TXT文本内容为 小高-20张三-18李四-19 private void btnInput_Click(object ...
- EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载
之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需要用的,这个系列讲讲如何使用EF操作数据库.老版本的EF主要是通过Ob ...
随机推荐
- 2016年2月---Javascript
How to Learn JavaScript Properly 如何正确学习JavaScript Learn Intermediate and Advanced JavaScript 书籍: < ...
- CTSC2016&&APIO2016游记
4.30 下午衡中放假,我们因为比赛的缘故提前到中午12:00放假 然后我爸爸说要来接我,直到下午两点多他才到,然后衡中宿舍的楼管阿姨死活不给我开门 莫名其妙的等到了三点多快四点的时候我才跟实验班的一 ...
- 再谈PCA
其实之前写过PCA相关的博文,但是由于之前掌握的理论知识有限,所以理解也比较浅.这篇博文,我们以另外一种角度来理解PCA看,这里我假设大家对PCA都有一个初步的了解.首先,我们举一个二维空间中 ...
- JavaEE5种常见的设计模式
1.工厂模式:比如你写了个应用,里面用到了数据库的封装,你的应用可以今后需要在不同的数据库环境下运行,可能是oracle,db2,sql server等, 那么连接数据库的代码是不一样的,你用传统的方 ...
- C#基础练习(使用委托窗体传值)
主界面: Form1中的代码: namespace _06委托练习_窗体传值 { public partial class Form1 : Form { public ...
- SQL效率问题
关于in和or的效率对比:http://blog.chinaunix.net/uid-20639775-id-3416737.html 在没有索引的情况下,in的效率高 SQL语句效率:http:// ...
- option配置
wildignore:用来设置忽略的文件匹配模式,shell模式
- 数据库MySQL-Oracle-DB2-SQLServer分页查询
1. MySQL分页查询 (1)关键字: LIMIT beginIndex, maxRow (2)示例: LIMIT子句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数. 如果给出 ...
- Android下 ionic view 无法登录
ionic view一个超棒工具,它是测试 ionic 框架搭建项目的app软件. 在它的官网有iphone 和 android 版本的下载地址.但是,这里只有在 google play 里面才有,而 ...
- 1888. Pilot Work Experience(dfs+bfs)
1888 dfs找出连通块 块内构造数据 bfs找出最值 如果有多个连通块 那max就为49 可以起点不同 这样记得修改后面的数据 写的老长了.. #include <iostream> ...