UPDATE Products SET ProductName = @ProductName, UnitPrice = @UnitPrice WHERE ProductID = @original_ProductID AND ProductName = @original_ProductName AND UnitPrice = @original_UnitPrice
注意:这个UPDATE语句是为了易读而简单化了。实际上,在WHERE子句中检测UnitPrice会比较棘手,这是因为UnitPrice可以包含空值,而NULL = NULL则总是返回False(相应地你必须用IS NULL)。
除了使用一个不同的UPDATE语句之外,配置TableAdapter使用开放式并发控制还需要修改它直接发送到数据库的方法。回到我们的第一节,创建一个数据访问层,这些发送到数据库的方法接收一列标量的值作为输入参数(不仅仅是强类型DataRow或DataTable的实例)。当使用开放式并发,直接发送到数据库的Update() 和 Delete()方法就包含了对应原始值的输入参数。而且,业务逻辑层中批量方式更新的代码(Update()的重载,它不仅接受标量值,也接受DataRows 和 DataTables)也要做出相应的更改。
与其扩展我们现有得数据访问层表适配器使用开放式并发(同时也必须修改业务逻辑层以协调),不如让我们创建一个新的类型化数据集NorthwindOptimisticConcurrency,在它里面我们添加一个使用开放式并发的Products表适配器。然后,我们将在业务逻辑层中创建类ProductsOptimisticConcurrencyBLL,它为了支持开放式并发的DAL会有适当的更改。一旦这些基础工作都已完成,我们就可以创建ASP.NET页面。
第二步: 创建一个支持开放式并发的数据访问层
为了创建一个新的类型化数据集,在App_Code文件夹里的DAL文件夹上右键点击,选择添加一个新的数据集并命名为NorthwindOptimisticConcurrency。正如我们在第一节中看到过的那样,系统会自动添加一个表适配器(TableAdapter)到当前的类型化数据集众,并自动地进入TableAdapter配置向导。在第一屏中,向导提示我们选择数据库连接 – 连接到同样的数据库Northwind并使用Web.config里设置好的连接字符串NORTHWNDConnectionString。
图 3: 连接到同一个数据库Northwind
下一步,向导提示我们选择如何访问数据库:通过一个指定的SQL语句,创建新的存储过程,或者使用一个现有的存储过程。既然我们最初的DAL是使用的是指定SQL查询语句,这里我们还是使用它。
图4: 使用指定SQL语句的方式访问数据库
下一步,进入查询分析器,返回产品信息。让我们使用在最初的DAL中产品TableAdapter相同的SQL查询,它返回产品的所有字段包括产品的供应商和类别名称。
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued, (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = Products.CategoryID) as CategoryName, (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) as SupplierName FROM Products
图5:使用在最初的DAL中产品TableAdapter相同的SQL查询
在我们进入下一步之前,点击“高级选项”按钮。要让这个TableAdapter使用开放式并发,仅仅需要勾选上“使用开放式并发”。
图6:勾选“使用开放式并发”启用开放式并发控制
最后,需要指出的是,该TableAdapter应该同时使用“填充DataTable”和“返回DataTable”两种要生成的方法;并且,勾选“创建方法以将更新直接发送到数据库(GenerateDBDirectMethods)”。将返回DataTable的方法名称从GetData改为GetProducts,使之与我们最初的DAL中的命名规则匹配。
图7:让这个TableAdapter利用所有的数据访问方式