使用SqlDataSource插入、更新以及删除数据

原创 2009年05月19日 15:34:00

概述插入、更新和删除数据 中我们讨论过, GridView 控件提供了内建的更新与删除功能,而 DetailsView FormView 控件除了这些之外还拥有插入功能。这些数据修改功能可以直接接入到数据源控件中而不需要编写任何代码。 概述插入、更新和删除数据 讲解了如何使用 ObjectDataSource 来帮助 GridView DetailsView 以及 FormView 控件完成插入、更新以及删除操作。 ObjectDataSource 能工作的地方, SqlDataSource 也行。

 

回忆一下,要使 ObjectDataSource 支持插入、更新和删除功能,我们需要定义一些用以执行插入、更新和删除动作的对象层方法。而在 SqlDataSource 中,我们则需要提供 INSERT UPDATE 以及 DELETE 语句(或存储过程)。正如我们将要在本节教程中看到的那样,这些语句可以手工创建,也可以通过 SqlDataSource 的“配置数据源”向导自动生成。

 

注意: 由于我们已经讨论过了 GridView DetailsView 以及 FormView 控件的插入、编辑和删除功能,本教程中我们将重点讨论如何配置 SqlDataSource 以使其支持这些操作。如果你需要温习一下如何在 GridView DetailsView 以及 FormView 中实现这个功能,请回到“编辑插入和删除数据”的章节,从 概述插入、更新和删除数据 开始。

 

第一步:指定 INSERT UPDATE 以及 DELETE 语句

就像我们在上两节教程中看到的那样,要从 SqlDataSource 控件中获取数据,我们需要设置两个属性:

1.  ConnectionString ,它指定了查询应该发送到的那个数据库;

2.  SelectCommand ,它指定了用于返回记录的 SQL 语句或存储过程。

 

对于带参数的 SelectCommand ,其参数值通过 SqlDataSource SelectParameters 集合来进行指定,可以包含硬编码值和通用参数源(比如 QueryString Session Web 控件等等),也可以通过编程的方式来对其进行赋值。当 SqlDataSource 控件的 Select() 方法被调用时(无论是通过编程来调用或是由数据 Web 控件自动调用),一个数据库连接将被建立,然后参数值被赋值给查询,然后 command 被发送到数据库。结果将以 DataSet DataReader 的形式返回,具体的返回形式取决于这个控件的 DataSourceMode 属性的值。

 

除了获取数据之外, SqlDataSource 还可以以非常相似的办法通过提供 INSERT UPDATE 以及 DELETE 语句来插入、更新以及删除数据。只需简单的给 InsertCommand UpdateCommand 以及 DeleteCommand 属性赋上 INSERT UPDATE 以及 DELETE 语句就可以了。如果语句带有参数(这也是常有的事),把这些参数放到 InsertParameters UpdateParameters 以及 DeleteParameters 集合里就可以了。

 

一旦 InsertCommand UpdateCommand DeleteCommand 的值被指定,相应数据 Web 控件的智能标签中的 允许插入 允许编辑 允许删除 选项将会变为可用。为了说明这个问题,我们就以在教程 使用 SqlDataSource 控件查询数据 中创建的 Querying.aspx 为例,给它加上删除功能。

 

首先从 SqlDataSource 文件夹中打开 InsertUpdateDelete.aspx Querying.aspx 。在 Querying.aspx 的设计器中选择第一个例子中的 SqlDataSource GridView (就是 ProductsDataSource GridView1 )。选好了这两个控件之后,在“编辑”菜单中选择“复制”(或者直接 Ctrl+C )。然后,到 InsertUpdateDelete.aspx 的设计器中,并将这两个控件粘贴上去。将这两个控件弄到 InsertUpdateDelete.aspx 上之后,在浏览器中测试一下这个页面。你应该看到 Products 表中所有记录的 ProductID ProductName 以及 UnitPrice

 

 

图一: 所有的产品都列出来了,并以 ProductID  进行了排序

 

添加 SqlDataSource DeleteCommand 以及 DeleteParameters   属性

现在,我们拥有了一个简单的从 Products 表返回所有记录的 SqlDataSource 和一个用以显示这些数据的 GridView 。我们的目标是扩展这个例子以允许用户可以通过 GridView 来删除产品。要达到这个目标,我们需要给 SqlDataSource 控件的 DeleteCommand 以及 DeleteParameters 属性指定相关的值,并配置 GridView 以使其可以支持删除。

 

DeleteCommand 以及 DeleteParameters 属性可以通过很多种方式进行指定:

· 通过声明标记代码;

· 通过设计器的属性窗口;

· 通过“配置数据源”向导中的  “ 指定一个自定义 SQL 语句或存储过程 页;

·   通过“配置数据源”向导中的“指定一个表或视图中的列”页上面的“高级”按钮,它将自动的生成 DELETE 语句,并自动生成 DeleteCommand 以及 DeleteParameters 属性所使用到的那些参数集合。

 

我们将在第二步中解释如何自动创建一个 DELETE 语句。虽然“配置数据源”向导或声明标记代码也 OK ,不过现在我们还是使用设计器中的属性窗口。

 

InsertUpdateDelete.aspx 的设计器中,单击一下 ProductsDataSource ,然后打开属性窗口(在“视图”菜单中选择“属性窗口”,或直接按 F4 )。选择 DeleteQuery 属性。

 

 

图二: 在属性窗口中选择 DeleteQuery 属性

 

注意: SqlDataSource 并没有 DeleteQuery 属性。事实上, DeleteQuery DeleteCommand DeleteParameters 属性的结合体,它仅仅在通过设计器查看属性窗口时才显示在那里。如果你在源视图中查看属性窗口,你将只能找到 DeleteCommand 属性。

 

点击 DeleteQuery 属性中的那个按钮,这时会弹出“命令和参数编辑器”对话框(见图三)。在这里,你可以指定 DELETE 语句并为其指定参数。在“ DELETE 命令”输入框中填上如下代码(你可以手工填写,也可以使用查询生成器,反正随你高兴):

 

1 DELETE   FROM  Products
2 WHERE  ProductID  =   @ProductID

 

 

然后,点击“刷新参数”按钮以将 @ProductID 参数添加到下面的参数列表中。

 

 

图三: 命令和参数编辑器(译者注:原文错了,“ Select the DeleteQuery Property from the Properties Window ”,这是图二的描述)

 

不要 给这个参数赋值(保留其参数源为“无”)。在我们向 GridView 添加了删除支持后, GridView 将通过其 DataKeys 集合为按下了删除按钮的那一行自动提供这个参数值。

 

注意: DELETE 语句中使用的参数名 必须 GridView DetailsView FormView DataKeyNames 相同。也就是说,我们专门把 DELETE 中的那个参数命名为 @ProductID (而不是 @ID ),是因为 Products 表中主键列的名称为 ProductID ( 因此 GridView DataKeyNames 值也是这个 ) 。如果参数名与 DataKeyNames 不同, GridView 将无法自动通过其 DataKeys 集合为这个参数赋值。

 

在“命令和参数编辑器”对话框中输入了与删除相关的信息之后,点击“确定”,并去到源视图中看看现在的声明标记代码:

 

1 < asp:SqlDataSource  ID ="ProductsDataSource"  runat ="server"
2     ConnectionString ="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
3     SelectCommand =
4         "SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products]"
5     DeleteCommand ="DELETE FROM Products WHERE ProductID = @ProductID" >
6      < DeleteParameters >
7          < asp:Parameter  Name ="ProductID"   />
8      </ DeleteParameters >
9 </ asp:SqlDataSource >

 

 

注意看看新添加的 DeleteCommand 属性和 <DeleteParameters> 节,还有名为 productID   Parameter 对象。

 

配置 GridView 以使其可以删除

由于添加了 DeleteCommand 属性, GridView 的智能标签现在有了“允许删除”选项。勾上这个复选框。就像我们在 概述插入、更新和删除数据 中所讨论的那样,在 GridView ShowDeleteButton 属性设为 true 的时候,这将使其添加一个 CommandField 。如图四所示,当通过浏览器访问这个页面时, GridView 中将包含一个删除按钮。通过删除一些产品来测试一下这个页面吧。


 

图四: 现在,每一个 GridView 行都包含了一个删除按钮

 

点击删除按钮之后,会引发一个回发,然后 GridView 将这一行的 DataKeys 集合赋值给 ProductID 参数,并调用 SqlDataSource Delete() 方法。接着, SqlDataSource 控件就连接上数据库并执行这个 DELETE 语句。最后 GridView 重新绑定这个 SqlDataSource ,并显示现在的产品集(刚刚被删除的那条记录就不见了)。

 

注意: 由于 GridView 使用其 DataKeys 集合来存放 SqlDataSource 的参数,所以我们必须注意要将 GridView DataKeyNames 属性设置为主键列(也可能是复合主键),而且 SqlDataSource SelectCommand 还必须要返回这些列才行。此外,将 SqlDataSource DeleteCommand 中的参数名设置为 @ProductID 也是非常重要的。如果没有设置 DataKeyNames 属性,或者参数没有命名为 @ProductsID ,在点击删除按钮只会,虽然还是会有一个回发,但是将不会删除任何行。

 

图五向我们形象的描述了这个交互过程。可以参考教程 研究插入、更新和删除的关联事件 以获取更多的有关通过数据 WEB 控件进行增删改操作所关联的事件链的详细信息。

 

 

图五: GridView 中点击了删除按钮之后将调用 SqlDataSource Delete() 方法

 

第二步:自动生成 INSERT UPDATE 以及 DELETE 语句

在第一步中我们了解到, INSERT UPDATE 以及 DELETE 语句可以通过属性窗口或控件的声明标记代码来进行指定。不过,这需要我们手工编写 SQL 语句,这不仅无聊而且还容易出错。还好,“配置数据源”向导的 指定一个表或视图中的列 页上提供了一个用于自动生成 INSERT UPDATE 以及 DELETE 语句的选项。

 

好了,我们去看看这个自动生成的选项。在 InsertUpdateDelete.aspx 的设计器中添加一个 DetailsView ,并将其 ID 属性设置为 ManageProducts 。然后,在 DetailsView 的智能标签中选择创建一个新的数据源,并将其命名为 ManageProductsDataSource

 

 

图六: 创建一个名为 ManageProductsDataSource SqlDataSource

 

在“配置数据源”中选择 NORTHWINDConnectionString ,然后点击“下一步”。在“配置 Select 语句”页中,选中“指定一个表或视图中的列”单选框,并在下拉框中选择 Products 表。然后在下面的复选框列表中选中 ProductID ProductName UnitPrice 以及 Discontinue 列。

 

 

图七: 使用 Products 表,返回其 ProductID ProductName UnitPrice 以及 Discontinue

 

要根据选好的表和列自动生成 INSERT UPDATE 以及 DELETE 语句,点击“高级”按钮并勾上“生成 INSERT UPDATE 以及 DELETE 语句”复选框。

 

 

图八: 勾上“生成 INSERT UPDATE 以及 DELETE 语句”复选框

 

只有当被选择的表含有主键且主键列包含在需要返回的列中时,“生成 INSERT UPDATE 以及 DELETE 语句”复选框才会变为可选状态。在“生成 INSERT UPDATE 以及 DELETE 语句”复选框被选中之后,“使用乐观并发”复选框也会变为可选状态,它将会给最终的 UPDATE DELETE 语句添加一个 WHERE 子句以提供乐观并发控制。不过,现在我们不选它,我们会在下一节中介绍如何通过 SqlDataSource 进行乐观并发控制。

 

勾上了“生成 INSERT UPDATE 以及 DELETE 语句”复选框之后,点击“确定”以返回“配置 Select 语句”页,然后点击“下一步”,接着点击“完成”以结束“配置数据源”向导。在完成了这个向导之后, Visual Studio 将立刻为 DetailsView 添加一些字段,其中 ProductID ProductName UnitPrice 对应的是 BoundFields Discontinued 对应的是 CheckBoxField 。在 DetailsView 的智能标签中,选中“允许分页”以使用户在访问这个页面时可以一页一页的查看产品。还有清除 DetailsView Width Height 属性。

 

注意一下,这个智能标签中的“允许插入”、“允许编辑”以及“允许删除”的选项现在已经是可用的了。这是因为 SqlDataSource InsertCommand UpdateCommand 以及 DeleteCommand 都含有了相应的 SQL 语句。其声明标记代码如下所示:

 

 1 < asp:DetailsView  ID ="ManageProducts"  runat ="server"  AllowPaging ="True"
 2     AutoGenerateRows ="False"  DataKeyNames ="ProductID"
 3     DataSourceID ="ManageProductsDataSource"  EnableViewState ="False" >
 4      < Fields >
 5          < asp:BoundField  DataField ="ProductID"  HeaderText ="ProductID"
 6             InsertVisible ="False"  ReadOnly ="True"  SortExpression ="ProductID"   />
 7          < asp:BoundField  DataField ="ProductName"  HeaderText ="ProductName"
 8             SortExpression ="ProductName"   />
 9          < asp:BoundField  DataField ="UnitPrice"  HeaderText ="UnitPrice"
10             SortExpression ="UnitPrice"   />
11          < asp:CheckBoxField  DataField ="Discontinued"  HeaderText ="Discontinued"
12             SortExpression ="Discontinued"   />
13      </ Fields >
14 </ asp:DetailsView >
15
16 < asp:SqlDataSource  ID ="ManageProductsDataSource"  runat ="server"
17     ConnectionString ="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
18     DeleteCommand =
19         "DELETE FROM [Products] WHERE [ProductID] = @ProductID"
20     InsertCommand =
21         "INSERT INTO [Products] ([ProductName], [UnitPrice], [Discontinued])
22          VALUES (@ProductName, @UnitPrice, @Discontinued)"
23     SelectCommand =
24         "SELECT [ProductID], [ProductName], [UnitPrice], [Discontinued]
25          FROM [Products]"
26     UpdateCommand =
27         "UPDATE [Products] SET [ProductName] = @ProductName,
28          [UnitPrice] = @UnitPrice, [Discontinued] = @Discontinued
29          WHERE [ProductID] = @ProductID" >
30      < DeleteParameters >
31          < asp:Parameter  Name ="ProductID"  Type ="Int32"   />
32      </ DeleteParameters >
33      < UpdateParameters >
34          < asp:Parameter  Name ="ProductName"  Type ="String"   />
35          < asp:Parameter  Name ="UnitPrice"  Type ="Decimal"   />
36          < asp:Parameter  Name ="Discontinued"  Type ="Boolean"   />
37          < asp:Parameter  Name ="ProductID"  Type ="Int32"   />
38      </ UpdateParameters >
39      < InsertParameters >
40          < asp:Parameter  Name ="ProductName"  Type ="String"   />
41          < asp:Parameter  Name ="UnitPrice"  Type ="Decimal"   />
42          < asp:Parameter  Name ="Discontinued"  Type ="Boolean"   />
43      </ InsertParameters >
44 </ asp:SqlDataSource >

 

 

注意一下 SqlDataSource 控件是如何自动为其 InsertCommand UpdateCommand 以及 DeleteCommand 属性赋值的。 InsertCommand UpdateCommand 以及 DeleteCommand 属性中所引用的列都是根据 SELECT 语句得到的。也就是说, InsertCommand UpdateCommand 将只含有那些在 SelectCommand 中被指定的列,而不是 Products 表的 所有 列(除了 ProductID ,它被忽略是因为它是一个 IDENTITY ,而 IDENTITY 列的值是不能修改的,只能在插入时自动赋值)。还有, InsertCommand UpdateCommand 以及 DeleteCommand 属性的每一个参数都存在于相应的 InsertParameters UpdateParameters 以及 DeleteParameters 集合中。

 

要打开 DetailsView 的数据修改功能,在其智能标签中构上“允许插入”、“允许编辑”以及“允许删除”选项就可以了。当 DetailsView ShowInsertButton ShowEditButton 以及 ShowDeleteButton 属性被设置为 true 时,就会加上相应的 CommandField 了。

 

现在通过浏览器访问这个页面时,就可以看到 DetailsView 有了 Edit Delete 以及 New 按钮了。点击 Edit 按钮将使 DetailsView 进入编辑模式,这时将把那些 ReadOnly 属性为 false BoundField 显示为 TextBox CheckBoxField 则显示为 CheckBox

 

 

图九: DetailsView 默认的编辑界面

 

同样,这里你也可以删除选中的产品或添加一个新的产品到系统中。由于 InsertCommand 只有 ProductName UnitPrice Discontinued 列,所以在向数据库插入记录时其他的列将为 NULL 或该列的默认值。跟 ObjectDataSource 一样,如果 InsertCommand 遇到某个拥有不允许为空又没有默认值的字段的表,在试图执行 INSERT 语句的时候就会引发一个 SQL 错误。

 

注意: DetailsView 的插入和编辑界面没有任何自定义或验证能力。要添加验证控件或是要自定义界面,你需要将 BoundField 转换为 TemplateField 。具体的办法可以参见 给编辑和新增界面增加验证控件 定制数据修改界面 。对了,要记住 DetailsView 在更新和删除时使用的是当前产品的 DataKey ,而这个 DataKey 仅在配置了 DataKeyNames 属性之后才能用。如果编辑或删除操作没有任何效果,那么你就要看看是不是没有设置 DataKeyNames 属性了。

 

自动生成 SQL 语句的局限性

由于“生成 INSERT UPDATE 以及 DELETE 语句”选项仅在从一个表中选择了一些列之后才可用,如果要弄一个复杂些的查询,那么你就不得不像我们在第一步中做的那样,自己编写 INSERT UPDATE 以及 DELETE 语句。通常,为了显示的需要, SELECT 语句会使用 JOIN 来从一个或多个子表中查找数据(比如在显示产品信息时,我们还需要从 Categories 表中得到相应 CategoryName 字段)。但同时我们可能仍然希望允许用户编辑、更新或插入(译者注:原文就是这样的,实际上应该是增删改操作)数据到“核心”表中(这里就是 Products 表)。

 

虽然可以通过手工方式输入 INSERT UPDATE 以及 DELETE 语句,但还是请考虑一下下面的节约时间的小贴士。首先将 SqlDataSource 设置为只仅可以返回 Products 表中的数据。使用“配置数据源”向导的“指定一个表或视图的列”页,这样你就可以自动的创建 INSERT UPDATE 以及 DELETE 语句。在完成了这个向导之后,再从属性窗口中配置 SelectQuery (或者回到“配置数据源”向导,只不过这次使用“指定一个自定义 SQL 语句或存储过程”)。然后修改 SELECT 语句以给它加上 JOIN 。这样,你既通过自动生成 SQL 语句而节约了时间,又可以自定义 SELECT 语句以使其更加复杂。

 

自动生成 INSERT UPDATE 以及 DELETE 语句的另一个限制是,它们的列 ( 只有 INSERT UPDATE ,这里不关 DELETE 的事 ) 都是基于 SELECT 语句所返回的列的。然而,我们可能需要更新或插入更多或更少的字段。比如在第二步的例子中,我们可能希望 UnitPrice  BoundField 是只读的,这时它就不应该出现在 UpdateCommand 中。或者我们可能希望给表中某个并没有显示在 GridView 中的字段设置一个值,比如当添加一个新记录时,我们可能希望把 QuantityPerUnit 设置为 “TODO”

 

如果有这样的自定义需求,你就需要通过属性窗口,或是向导中的“指定一个自定义 SQL 语句或存储过程”选项,或是声明标记代码来手工的完成这些工作。

 

注意: 当添加一个在数据 Web 控件中没有相应字段的参数时,记住一定要通过某种方式为这个参数赋值。这个参数可以:直接在 InsertCommand UpdateCommand 中硬编码;来自某个预定义的源( QueryString Session Web 控件……);或是像我们在前一节教程中看到的那样通过编程的方式来进行赋值。

 

总结

为了让数据 Web 控件可以利用其内建的插入、编辑以及删除功能,它们所绑定的数据源就必须实现相应的功能。对于 SqlDataSource 来说,这就意味着必须把 INSERT UPDATE 以及 DELETE 语句赋值给 InsertCommand UpdateCommand 以及 DeleteCommand 属性。这些属性及其相关的参数集合可以手工添加也可以在“配置数据源”向导中自动生成。本教程中,两种办法我们都介绍过了。

 

实现开放式并发 中,我们介绍了如何通过 ObjectDataSource 实现乐观并发(译者注:开放式并发就是乐观并发,相应的就是保守式并发和悲观并发)。 SqlDataSource 控件同样也提供了对乐观并发的支持。在第二步中我们注意到,当自动生成 INSERT UPDATE 以及 DELETE 语句时,向导提供了一个“使用乐观并发”的选项。我们将在下一节教程中看到,在 SqlDataSource 中使用乐观并发将会修改 UPDATE DELETE 语句的 WHERE 子句以保证从上次在本页显示数据到现在为止,其他列的值都没有被修改。

 

编程愉快!

 

关于作者

Scott Mitchell ,著有六本 ASP/ASP.NET 方面的书,是 4GuysFromRolla.com 的创始人,自 1998 年以来一直应用微软 Web 技术。 Scott 是个独立的技术咨询顾问,培训师,作家,最近完成了将由 Sams 出版社出版的新作, 24小时内精通 ASP.NET 2.0 。他的联系电邮为 mitchell@4guysfromrolla.com ,也可以通过他的博客 http://ScottOnWriting.NET 与他联系。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

SqlDatasource简单用法

<asp:Button ID="Delet

数据结构之算法时间复杂度

数据结构之算法时间复杂度原文链接 算法的时间复杂度定义为:在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也...

SQL两表之间:根据一个表的字段更新另一个表的字段

1. 写法轻松,更新效率高: update table1 set field1=table2.field1, field2=table2.field2 from table2 where ...

SQL——两个表之间的更新:用一个表的字段更新另一个表的字段

--1. 这种写法相当于一个 Left join, 以外面的where为更新条数。 -- 注意! 如果内面的表的(where之后取得的)条数比外面表的(where之后取得的)条数少, 会造成 不...

GitChat · 人工智能 | 用语音和自然语言控制智能家居——实例分享

GitChat 作者:晶晶郭 关注公众号:GitChat 技术杂谈,一本正经的讲技术 前言ZigBee作为一种短距离、低功耗的无线通信局域网协议,其优点是超低功耗、安全性高和自组网,并且可容纳多...

怎样将Oracle一张表的多个字段更新到另一张表中去

假设表a中有多个字段(province ,city)需要从b表获取(两张表的mobile一样),总结了几种写法。   一、update a  set a.province=(select prov...

TensFlow框架学习之MNIST机器学习入门

前言:初学TensorFlow和机器学习,MNIST算法的每条语句都不是很清楚,通过查阅资料,将每句代码的基本用法差不多理解了。希望能够帮助正在学习的你from tensorflow.examples...

SQL Update多表联合更新的方法

SQL Update多表联合更新的方法 (1) sqlite 多表更新方法 //---------------------------------- update t1 set col1=t2....
  • hsg77
  • hsg77
  • 2012-02-09 15:54
  • 120350

配置maven私服nexus

1、Nexus简介1.1 Nexus概述Nexus是一个强大的Maven仓库管理器,它极大地简化了自己内部仓库的维护和外部仓库的访问。利用Nexus你可以只在一个地方就能够完全控制访问和部署在你所维护...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)