一般情况下我们要对数据库访问进行并发控制,假如我们要手动实现这样的效果的话,我们先把数据取出来,这些数据要保存两份,一份让用户进行修改,一份供我们进行数据访问控制使用,当用户修改数据后要进行保存,我们在写入数据的时候,要先进行数据的比较,看数据库数据与读出时的数据是否相同(比较时采用的是第二份数据),如不相同,则证明用户在读出数据后,已有用户对该数据进行了修改,不保存。反之则进行保存。这个东西说起来的时候就比较烦了,更何况用编程去实现呢,呵呵,还为“数据集”已经为我们考虑好了,呵呵!这次我们使用Table2表
新建一个数据集DataSet2,按照文章1中的步骤进行,选择使用SQL语句,输入语句
SELECT Table2.* FROM Table2,点击左下角的高级选项,勾上第一,二选项,接下来点击下一步,直至它们完成就可以了。完成之后我们点击菜单上的“生成”—》“生成解决方案”,让其生成相应的类。
接下来做表示层,同样往页面上放一个ObjectDataSource和GridView,接下来配置一下ObjectDataSource,它的业务对象选择DataSet2TableAdapters.Table2TableAdapter,按其默认选项完成设置。GridView的数据源选择刚才设置的ObjectDataSource,然后它就可以显示了,按F5先看一下效果,如图:
然后往GridView上面添加编辑,删除列,运行后如图所示:
另高兴得太早,好玩的还在后面呢,我们点击编辑,修改后更新,出现以下的错误。
值不能为空。
参数名: Original_username
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.ArgumentNullException: 值不能为空。
参数名: Original_username
这可不是因为文章1中的原因,我们先看一下我们的Update语句
<CommandText>UPDATE [Table2] SET [username] = @username, [password] = @password, [email] = @email, [address] = @address WHERE (([id] = @Original_id) AND ([username] = @Original_username) AND ([password] = @Original_password) AND ((@IsNull_email = 1 AND [email] IS NULL) OR ([email] = @Original_email)) AND ((@IsNull_address = 1 AND [address] IS NULL) OR ([address] = @Original_address)))</CommandText>
我们的主键是自动标识的,所以不会出现文章1中的情况,问题原因所在是它在进行更新时要对比原有的数据,以防在读取数据之后,进行数据修改之前,有用户对其进行了修改,从而达到数据并发访问控制的目的。
解决的方法:
其实也说不上解决的方法吧,只是我们使用时比较容易忽略掉吧,将ObjectDataSource的属性ConflictDetection值OverwriteChanges改成CompareAllValues,它在更新时就会传递参数进行比较了。
在NET里面实现数据的并发访问控制是不是很简单呀,呵呵。