16概述插入更新和删除数据.docx
《16概述插入更新和删除数据.docx》由会员分享,可在线阅读,更多相关《16概述插入更新和删除数据.docx(34页珍藏版)》请在冰豆网上搜索。
16概述插入更新和删除数据
导言
结束前面的几节,我们已经探讨过了如何使用GridView、DetailsView和FormView控件来显示数据。
这些控件简单地操作提供给它的数据。
一般地,这些控件通过使用一个数据源控件,例如ObjectDataSource来存取数据。
我们已经看过了ObjectDataSource是如何在ASP.NET页面和潜在的数据之间扮演一个代理的角色。
当一个GridView需要显示数据时,它调用ObjectDataSource的Select()方法,这个方法转而调用一个来自我们的业务逻辑层(BLL)的方法,继而调用一个适当的数据访问层(DAL)的表适配器(TableAdapter)的方法,从而它发送一个SELECT查询到Northwind数据库。
记得在我们的教程里当创建DAL中的表适配器时,VisualStudio自动地添加从潜在数据库插入、更新和删除数据的方法。
此外,在创建一个业务逻辑层这一节我们已经设计了调用这些数据更改的DAL方法的BLL方法。
除了它的Select()方法,ObjectDataSource还有Insert()、Update()和Delete()方法。
跟Select()方法类似,这三个方法映射到一个隐含的对象。
当配置插入、更新或删除数据时,GridView、DetailsView和FormView控件提供了一个修改潜在的数据的用户界面。
这个用户界面调用ObjectDataSource的Insert()、Update()和Delete()方法,它们继而调用隐含对象的关联方法(见图1)。
图1:
ObjectDataSource的Insert()、Update()和Delete()方法提供一个到BLL的代理
本节我们将看看如何映射ObjectDataSource的Insert()、Update()和Delete()方法到BLL中的类,也看看如何配置GridView、DetailsView和FormView控件提供修改数据的功能。
第一步:
创建Insert、Update和Delete教程页面
在我们开始探讨如何插入、修改和删除数据之前,让我们先花些时间在我们的站点项目里添加这些本节里和下一节里需要的ASP.NET页面。
首先添加一个名为EditInsertDelete的新文件夹。
然后,在这个文件夹里添加下面这些ASP.NET页面,并且确认每个页面都关联Site.master母版页:
· Default.aspx
· Basics.aspx
· DataModificationEvents.aspx
· ErrorHandling.aspx
· UIValidation.aspx
· CustomizedUI.aspx
· OptimisticConcurrency.aspx
· ConfirmationOnDelete.aspx
· UserLevelAccess.aspx
图2:
添加这些与数据更改关联的教程的页面
类似在其它文件夹里,EditInsertDelete文件夹里的Default.aspx将列出这些教程章节。
记得用户控件提供这个功能。
因此,从解决方案资源管理器中拖拽一个这个用户控件到页面的设计视图,从而添加它到Default.aspx页面。
图3:
添加SectionLevelTutorialListing.ascx用户控件到tDefault.aspx页面
最后,添加这些页面地址项到Web.sitemap文件。
明确地,在CustomizedFormatting后添加如下标记:
在更新了Web.sitemap后,花些时间通过浏览器访问本教程站点。
左边的菜单里现在包含对应编辑、插入和删除教程的项。
图4:
站点地图现在包含了对应编辑、插入和删除教程的项
第二步:
添加并配置ObjectDataSource控件
因为GridView、DetailsView和FormView控件在数据修改功能和版面上都有所不同,就让我们逐个研究。
不过,与其让这三个控件各自使用自己的ObjectDataSource,还不如让我们仅创建一个ObjectDataSource让这个三个控件的例子共用。
打开Basics.aspx页面,从工具箱拖拽一个ObjectDataSource到设计器,从它的职能标记中点击配置数据源链接。
因为ProductsBLL类是唯一一个提供修改、插入和删除方法的BLL类,配置该ObjectDataSource使用这个类。
图5:
配置ObjectDataSource使用ProductsBLL类
在下一屏中,通过选择适当的tab页并从下拉列表中选择方法,我们可以指定ProductsBLL类里的哪些方法被映射到ObjectDataSource的Select()、Insert()、Update()和Delete()方法。
图6,至今我们应该很熟悉,映射ObjectDataSource的Select()方法到ProductsBLL类的GetProducts()方法。
Insert()、Update()和Delete()方法可以通过选择上方的适当的tab页进行配置。
图6:
让这个ObjectDataSource返回所有产品
图7、8和9显示ObjectDataSource的UPDATE、INSERT,和DELETE的tab页。
配置它们从而Insert()、Update()和Delete()方法分别调用ProductsBLL类的UpdateProduct、AddProduct和DeleteProduct方法。
图7:
映射ObjectDataSource的Update()方法到ProductBLL类的UpdateProduct方法
图8:
映射ObjectDataSource的Insert()方法到ProductBLL类的AddProduct方法
图9:
映射ObjectDataSource的Delete()方法到ProductBLL类的DeleteProduct方法
你也许已经注意到在UPDATE、INSERT和DELETE的tab页里的下拉列表中已经选择了各自的方法。
这是由于我们使用了DataObjectMethodAttribute,它修饰了ProducstBLL类。
例如,DeleteProduct方法是如下这样子声明的:
[System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Delete,true)]
publicboolDeleteProduct(intproductID)
{
...
}
DataObjectMethodAttribute指示每一个方法的目的–是否为了查询、插入、更新或删除–
是否它的默认值。
如果你在创建BLL类的时候省略了这些属性,现在你将需要手工从UPDATE、INSERT和DELETE的tab页里手工选择方法。
当确认已经适当的ProductsBLL方法映射到ObjectDataSource的Insert()、Update()和Delete()方法后,点击完成结束此向导。
检查ObjectDataSource的标记
在通过数据源配置向导完成了对ObjectDataSource的配置之后,到源视图去检查一下生成的声明标记。
ObjectDataSource>标签列明了隐含的对象和需要调用的方法。
另外,还有DeleteParameters、UpdateParameters和InsertParameters,它们映射ProductsBLL类的AddProduct、UpdateProduct和DeleteProduct方法的输入参数:
ObjectDataSourceID="ObjectDataSource1"runat="server"DeleteMethod="DeleteProduct"
InsertMethod="AddProduct"OldValuesParameterFormatString="original_{0}"SelectMethod="GetProducts"
TypeName="ProductsBLL"UpdateMethod="UpdateProduct">
ParameterName="productID"Type="Int32"/>
ParameterName="productName"Type="String"/>
ParameterName="supplierID"Type="Int32"/>
ParameterName="categoryID"Type="Int32"/>
ParameterName="quantityPerUnit"Type="String"/>
ParameterName="unitPrice"Type="Decimal"/>
ParameterName="unitsInStock"Type="Int16"/>
ParameterName="unitsOnOrder"Type="Int16"/>
ParameterName="reorderLevel"Type="Int16"/>
ParameterName="discontinued"Type="Boolean"/>
ParameterName="productID"Type="Int32"/>
ParameterName="productName"Type="String"/>
ParameterName="supplierID"Type="Int32"/>
ParameterName="categoryID"Type="Int32"/>
ParameterName="quantityPerUnit"Type="String"/>
ParameterName="unitPrice"Type="Decimal"/>
ParameterName="unitsInStock"Type="Int16"/>
ParameterName="unitsOnOrder"Type="Int16"/>
ParameterName="reorderLevel"Type="Int16"/>
ParameterName="discontinued"Type="Boolean"/>
ObjectDataSource>
ObjectDataSource包含了对应它关联的方法的每一个输入参数的parameter,就像当ObjectDataSource被配置为调用预期一个输入参数的查询方法(例如GetProductsByCategoryID(categoryID))时出现的SelectParameters一栏。
正如我们马上即将看到的,这些DeleteParameters、UpdateParameters和InsertParameters的值在调用ObjectDataSource的Insert()、Update()或Delete()方法之前自动地通过GridView、DetailsView和FormView被设置。
必要时这些值也可以通过编程设置,这在以后的章节里讨论。
使用数据源配置向导来配置ObjectDataSource的另一个影响是VisualStudio设置了OldValuesParameterFormatString属性为original_{0}。
这个属性值用来包含数据被编辑时的原始值,它在下面两种情况下非常有用:
· 如果,当编辑一条记录时,用户可以修改主键的值。
在这种情况下,新的主键的值和原始的主键值都需要提供,这样具有这个原始主键值的数据库记录才可以被找到然后才能将它的值更新。
· 当使用开放式并发。
开放式并发是为了保证同时操作的用户不至于覆盖另一个用户所做更改的一种技巧,这也是后面的教程中的一节(实现开放式并发)。
这个OldValuesParameterFormatString属性指明了隐含对象的更新和删除方法中对应原始值的输入参数的名称。
我们将在探讨开发式并发的时候更详细地讨论这个属性和它的目的。
不过暂时我放下它,因为我们的BLL的方法并不需要这些原始的值因此我们删除这个属性,这一点很重要。
如果让OldValuesParameterFormatString属性设置为除了默认值({0})以外的其它任何的值,都将在数据Web控件尝试调用ObjectDataSource的Update()或Delete()方法时引发一个错误,因为ObjectDataSource将尝试将这些原始值参数与UpdateParameters或DeleteParameters一起传入。
如果对此不是十分清楚,别担心,我们将在未来的章节中研究这个属性和它的效用。
暂时,一定要完全地从声明语法中完全地删除这个属性或者将它设置为默认值({0})。
注意:
如果你只是简单地从设计视图的属性窗口删除这个OldValuesParameterFormatString属性的值,这个属性依旧会存在于声明语法中,不过被设置为一个空字符串。
不幸地,这将依旧导致上面提到的同样的问题。
所以,从声明语法里彻底地删除这个属性,或者从属性窗口将其设置为默认值,{0}。
第三步:
添加一个数据Web服务器控件并配置它为数据更改服务
一般ObjectDataSOurce被添加到页面并配置完成,我们可以添加一个数据Web服务器控件用来显示数据并提供一个最终用户修改数据的途径。
我们将分别看看GridView、DetailsView和FormView,因为这些数据Web服务器控件在它们的数据更改功能和配置上都有所不同。
正如我们将在本文剩下的部分里看到的,通过GridView、DetailsView和FormView控件添加一个非常基本的编辑、插入和删除支持是真的非常简单,只需要勾选上一对CheckBox。
现实中提供这样的功能有许多微妙之处和边缘案例,这要比仅仅点几下要棘手得多。
但是,本教程里,只着眼于提供简单的数据修改功能。
以后的章节将研究在现实中不容置疑地出现的问题。
从GridView中删除数据
首先,从工具箱拖拽一个GridView到设计器。
然后,通过GridView的智能标记中从下拉列表中选择从而绑定ObjectDataSource到该GridView。
在这里GridView的声明标记将是:
GridViewID="GridView1"runat="server"AutoGenerateColumns="False"DataKeyNames="ProductID"DataSourceID="ObjectDataSource1"EnableViewState="False">
BoundFieldDataField="ProductID"HeaderText="ProductID"InsertVisible="False"
ReadOnly="True"SortExpression="ProductID"/>
BoundFieldDataField="ProductName"HeaderText="ProductName"SortExpression="ProductName"/>
BoundFieldDataField="SupplierID"HeaderText="SupplierID"SortExpression="SupplierID"/>
BoundFieldDataField="CategoryID"HeaderText="CategoryID"SortExpression="CategoryID"/>
BoundFieldDataField="QuantityPerUnit"HeaderText="QuantityPerUnit"SortExpression="QuantityPerUnit"/>
BoundFieldDataField="UnitPrice"HeaderText="UnitPrice"SortExpression="UnitPrice"/>
BoundFieldDataField="UnitsInStock"HeaderText="UnitsInStock"SortExpression="UnitsInStock"/>
BoundFieldDataField="UnitsOnOrder"HeaderText="UnitsOnOrder"SortExpression="UnitsOnOrder"/>
BoundFieldDataField="ReorderLevel"HeaderText="ReorderLevel"SortExpression="ReorderLevel"/>
CheckBoxFieldDataField="Discontinued"HeaderText="Discontinued"SortExpression="Discontinued"/>
BoundFieldDataField="CategoryName"HeaderText="CategoryName"ReadOnly="True"
SortExpression="CategoryName"/>
BoundFieldDataField="SupplierName"HeaderText="SupplierName"ReadOnly="True"
SortExpression="SupplierName"/>
GridView>
通过它的职