优化并行
Optimistic Concurrency
为了实现优化并行,WHERE语句应该包含原始值(DataSet会自动存储),这样就可以保证,如果另一个用户修改了记录,则该记录不会被更新。因此,无须预读记录,就能够写(一次),并且如果已经修改了记录,那么不会更新数据。
这种方法具有巨大的效率优势。在大多数情况中,更新是成功的,且不会被额外的数据库读取所打扰。如果更新成功,检查数据和更新之间不会存在滞后,这样其他人就不会有机会悄悄地另写一次。如果更新失败,则能够了解其中原因,并采取正确的行动。
为了让这种方式工作起来,如果数据库中的数据在获得数据后改变,更新必须失败。因为数据源能够告诉您它从数据库获得的原始值。您只须将这些原始值作为参数传递给存储过程,然后,在Update语句的Where子句中添加它们即可。换言之,必须扩展Where语句来指出“每个列的值没有改变的记录”。
当更新记录时,将检验原始值与数据库中的值。如果二者不同,那么只有在解决了由其他人与您之间更新记录的问题后,才可以更新记录。
为了说明如何实现,让我们回到优化并行。重新打开向导(单击数据源上的智能标签,然后单击“Next”>“Advanced …”),但是这次须要确保两个多选框都被选中。
单击“OK”按钮,然后是“Next”按钮,最后单击“Finish”按钮。再次检查源代码,如示例9-3所示。
示例9-3:具有优化并行的数据源控件
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
SelectCommand="SELECT * FROM [Customers]"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
DeleteCommand="DELETE FROM [Customers]
WHERE [CustomerID] = @original_CustomerID
AND [CompanyName] = @original_CompanyName
AND [ContactName] = @original_ContactName
AND [ContactTitle] = @original_ContactTitle
AND [Address] = @original_Address
AND [City] = @original_City
AND [Region] = @original_Region
AND [PostalCode] = @original_PostalCode
AND [Country] = @original_Country
AND [Phone] = @original_Phone
AND [Fax] = @original_Fax"
InsertCommand="INSERT INTO [Customers] ([CustomerID],
[CompanyName], [ContactName], ContactTitle], [Address], [City], [Region],
[PostalCode], [Country], [Phone], [Fax])
VALUES (@CustomerID, @CompanyName, @ContactName, @ContactTitle,
@Address, @City, @Region, @PostalCode, @Country, @Phone, @Fax)"
UpdateCommand="UPDATE [Customers] SET [CompanyName] = @CompanyName,
[ContactName] = @ContactName, [ContactTitle] = @ContactTitle,
[Address] = @Address, [City] = @City, [Region] = @Region,
[PostalCode] = @PostalCode, [Country] = @Country, [Phone] = @Phone,
[Fax] = @Fax
WHERE [CustomerID] = @original_CustomerID
AND [CompanyName] = @original_CompanyName
AND [ContactName] = @original_ContactName
AND [ContactTitle] = @original_ContactTitle
AND [Address] = @original_Address
AND [City] = @original_City
AND [Region] = @original_Region
AND [PostalCode] = @original_PostalCode
AND [Country] = @original_Country
AND [Phone] = @original_Phone
AND [Fax] = @original_Fax"
ConflictDetection="CompareAllValues">
<DeleteParameters>
<asp:Parameter Type="String" Name="original_CustomerID" />
<asp:Parameter Type="String" Name="original_CompanyName" />
<asp:Parameter Type="String" Name="original_ContactName" />
<asp:Parameter Type="String" Name="original_ContactTitle" />
<asp:Parameter Type="String" Name="original_Address" />
<asp:Parameter Type="String" Name="original_City" />
<asp:Parameter Type="String" Name="original_Region" />
<asp:Parameter Type="String" Name="original_PostalCode" />
<asp:Parameter Type="String" Name="original_Country" />
<asp:Parameter Type="String" Name="original_Phone" />
<asp:Parameter Type="String" Name="original_Fax" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Type="String" Name="CompanyName" />
<asp:Parameter Type="String" Name="ContactName" />
<asp:Parameter Type="String" Name="ContactTitle" />
<asp:Parameter Type="String" Name="Address" />
<asp:Parameter Type="String" Name="City" />
<asp:Parameter Type="String" Name="Region" />
<asp:Parameter Type="String" Name="PostalCode" />
<asp:Parameter Type="String" Name="Country" />
<asp:Parameter Type="String" Name="Phone" />
<asp:Parameter Type="String" Name="Fax" />
<asp:Parameter Type="String" Name="original_CustomerID" />
<asp:Parameter Type="String" Name="original_CompanyName" />
<asp:Parameter Type="String" Name="original_ContactName" />
<asp:Parameter Type="String" Name="original_ContactTitle" />
<asp:Parameter Type="String" Name="original_Address" />
<asp:Parameter Type="String" Name="original_City" />
<asp:Parameter Type="String" Name="original_Region" />
<asp:Parameter Type="String" Name="original_PostalCode" />
<asp:Parameter Type="String" Name="original_Country" />
<asp:Parameter Type="String" Name="original_Phone" />
<asp:Parameter Type="String" Name="original_Fax" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Type="String" Name="CustomerID" />
<asp:Parameter Type="String" Name="CompanyName" />
<asp:Parameter Type="String" Name="ContactName" />
<asp:Parameter Type="String" Name="ContactTitle" />
<asp:Parameter Type="String" Name="Address" />
<asp:Parameter Type="String" Name="City" />
<asp:Parameter Type="String" Name="Region" />
<asp:Parameter Type="String" Name="PostalCode" />
<asp:Parameter Type="String" Name="Country" />
<asp:Parameter Type="String" Name="Phone" />
<asp:Parameter Type="String" Name="Fax" />
</InsertParameters>
</asp:SqlDataSource>
不要大惊小怪。示例9-2和示例9-3的唯一区别在于,在示例9-3中,扩展了Where子句,以便保证记录没有被替换。DeleteCommand说明了这一点,而UpdateCommand也是这样工作的。
DeleteCommand="DELETE FROM [Customers]
WHERE [CustomerID] = @original_CustomerID
AND [CompanyName] = @original_CompanyName
AND [ContactName] = @original_ContactName
AND [ContactTitle] = @original_ContactTitle
AND [Address] = @original_Address
AND [City] = @original_City
AND [Region] = @original_Region
AND [PostalCode] = @original_PostalCode
AND [Country] = @original_Country
AND [Phone] = @original_Phone
AND [Fax] = @original_Fax"
因此,必须传入CustomerID参数,并传入所有字段的原始值:
<DeleteParameters>
<asp:Parameter Type="String" Name="original_CustomerID" />
<asp:Parameter Type="String" Name="original_CompanyName" />
<asp:Parameter Type="String" Name="original_ContactName" />
<asp:Parameter Type="String" Name="original_ContactTitle" />
<asp:Parameter Type="String" Name="original_Address" />
<asp:Parameter Type="String" Name="original_City" />
<asp:Parameter Type="String" Name="original_Region" />
<asp:Parameter Type="String" Name="original_PostalCode" />
<asp:Parameter Type="String" Name="original_Country" />
<asp:Parameter Type="String" Name="original_Phone" />
<asp:Parameter Type="String" Name="original_Fax" />
</DeleteParameters>
所有这些工作都由向导帮助完成。
向导将添加如下属性:
ConflictDetection="CompareAllValues"
参数ConflictDetection有两个可能的值,分别是CompareAllValues(在这种情况下,如果原始值已经改变,则不会更新数据库)和OverwriteChanges(在这种情况下,新值将重写旧值)。
警告:OverwriteChanges会覆盖任何人插入的数据,并将您的更新写入数据库。可以想象,该参数值很少使用,并且要慎用。多数情况下,使用的是CompareAllValues。







