1.从模板列里删除货币格式限制。就是说,取代<%# Bind("UnitPrice", "{0:C}") %>,简单地使用<%# Bind("UnitPrice") %>。下方的价格就是没有格式化的。
2.在模板列中显示UnitPrice时格式化为货币,但是使用Eval关键字实现绑定。记得Eval是实现单向绑定的。我们仍然需要提供UnitPrice的值作为原始的值,因此在模板列里我们依旧需要一个双向绑定的声明,但这可以放在一个Visible属性设置为false的Label服务器控件里。在模板列里我们可以使用下面的标记:
<ItemTemplate> <asp:Label runat="server" Text='<%# Bind("UnitPrice") %>' Visible="false"></asp:Label> <asp:Label runat="server" Text='<%# Eval("UnitPrice", "{0:C}") %>'></asp:Label> </ItemTemplate>
3.从模板列里删除货币格式限制,使用 <%# Bind("UnitPrice") %>。在GridView的RowDataBound事件处理里,编码访问显示UnitPrice的值的Label服务器控件并设置其Text属性为格式化的版本。
4.让UnitPrice保留货币格式化。在GridView的RowDeleting事件处理里,将现存的UnitPrice的原始($19.95)替换为实际的小数值(使用Decimal.Parse)。在前面的 在ASP.NET页面中处理BLL/DAL异常这一节教程里我们也已经看过如何RowUpdating事件处理里实现类似的功能。 在我的例程里我选择第二种方法,添加一个隐藏的Label服务器控件,并将它的Text属性双向绑定到无格式的UnitPrice值。解决了这个问题之后,再次点击任意一个产品的删除按钮。这一次,当ObjectDataSource尝试调用BLL的UpdateProduct方法时我们得到一个InvalidOperationException异常。
图 16: ObjectDataSource找不到具有它要发送的输入参数的方法
仔细看看异常信息,明显地ObjectDataSource希望调用一个BLL的DeleteProduct方法,此方法包含original_CategoryName和original_SupplierName输入参数。这是因为CategoryID和SupplierID模板列的ItemTemplate当前是双向绑定到CategoryName和SupplierName数据字段。作为替换,我们需要包含对CategoryID和SupplierID数据字段的Bind声明。为了实现这一点,把现有的Bind声明更改为Eval声明,并且添加隐藏的Label服务器控件,这些Label的Text属性使用双向绑定的方式绑定到CategoryID和SupplierID数据字段,如下所示:
<asp:TemplateField HeaderText="Category" SortExpression="CategoryName"> <EditItemTemplate> ... </EditItemTemplate> <ItemTemplate> <asp:Label runat="server" Text='<%# Bind("CategoryID") %>' Visible="False"></asp:Label> <asp:Label runat="server" Text='<%# Eval("CategoryName") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="Supplier" SortExpression="SupplierName"> <EditItemTemplate> ... </EditItemTemplate> <ItemTemplate> <asp:Label runat="server" Text='<%# Bind("SupplierID") %>' Visible="False"></asp:Label> <asp:Label runat="server" Text='<%# Eval("SupplierName") %>'></asp:Label> </ItemTemplate> </asp:TemplateField>
通过这些更改,现在我们可以成功地删除和编辑产品信息了!在第五步里,我们将看看如何验证删除时发生并发冲突。但是现在,花几分钟尝试更新和删除一些记录,确认在单用户的情况下更新和删除能够正常运作。
第五步: 测试开放式并发支持
为了验证并发冲突是否能够被发现(而不是导致数据被盲目改写),我们需要打开两个浏览器窗口来访问这个页面。在两个浏览窗口里,都点击产品“Chai”的编辑按钮。然后,在其中一个窗口修改其名称为“Chai Tea”并点击更新。这个更新应该会成功并且GridView回到预编辑状态,并且该产品的名称已经改为“Chai Tea”。
而在另一个浏览器窗口里,产品名称域依旧显示的是“Chai”。在这个浏览器窗口,将UnitPrice的值更新为25.00。如果没有开放式并发支持的话,点击第二个浏览器窗口的更新按钮将把产品名称改回“Chai”,从而覆盖了第一个浏览器窗口里所作的修改。然而现在有了开发式并发,当点击第二个窗口中的更新按钮时导致了一个DBConcurrencyException异常。
图 17: 发现并发冲突,抛出一个DBConcurrencyException异常