使用 SqlDataSource 插入、更新和删除数据 (VB)
在前面的教程中,我们了解了 ObjectDataSource 控件如何允许插入、更新和删除数据。 SqlDataSource 控件支持相同的操作,但方法不同,本教程演示如何配置 SqlDataSource 以插入、更新和删除数据。
简介
如 插入、更新和删除概述中所述,GridView 控件提供内置的更新和删除功能,而 DetailsView 和 FormView 控件包括插入支持以及编辑和删除功能。 这些数据修改功能可以直接插入数据源控件,而无需编写代码行。 使用 ObjectDataSource 检查插入、更新和删除概述,以方便使用 GridView、DetailsView 和 FormView 控件进行插入、更新和删除。 或者,可以使用 SqlDataSource 代替 ObjectDataSource。
回想一下,为了支持插入、更新和删除,需要使用 ObjectDataSource 指定要调用的对象层方法来执行插入、更新或删除操作。 使用 SqlDataSource 时,我们需要提供 INSERT
、 UPDATE
和 DELETE
SQL 语句, (或存储过程) 执行。 如本教程所示,这些语句可以手动创建,也可以由 SqlDataSource 的“配置数据源”向导自动生成。
注意
由于我们已经讨论了 GridView、DetailsView 和 FormView 控件的插入、编辑和删除功能,本教程将重点介绍如何配置 SqlDataSource 控件以支持这些操作。 如果需要深入了解如何在 GridView、DetailsView 和 FormView 中实现这些功能,请从插入、更新和删除概述开始,返回到编辑、插入 和删除数据教程。
步骤 1:指定 INSERT、UPDATE 和 DELETE 语句
正如我们在过去两个教程中看到的那样,若要从 SqlDataSource 控件检索数据,需要设置两个属性:
ConnectionString
,它指定要将查询发送到哪个数据库,以及SelectCommand
,指定要执行以返回结果的即席 SQL 语句或存储过程名称。
对于 SelectCommand
具有参数的值,参数值通过 SqlDataSource 集合 SelectParameters
指定,可以包括硬编码值、常见参数源值 (查询字符串字段、会话变量、Web 控件值等) ,也可以以编程方式分配。 以编程方式或从数据 Web 控件自动调用 SqlDataSource 控件 方法 Select()
时,会建立与数据库的连接,将参数值分配给查询,并将命令传递到数据库。 然后,根据控件 属性 DataSourceMode
的值,以 DataSet 或 DataReader 的形式返回结果。
除了选择数据之外,SqlDataSource 控件还可以通过以大致相同的方式提供 INSERT
、 UPDATE
和 SQL 语句来插入、更新和 DELETE
删除数据。 只需为 、 和 属性INSERT
分配要执行的 、 UPDATE
和 DELETE
SQL DeleteCommand
语句。 UpdateCommand
InsertCommand
如果语句具有 (参数,因为它们将始终) ,请将它们包含在 、 UpdateParameters
和 DeleteParameters
集合中InsertParameters
。
InsertCommand
指定 、 UpdateCommand
或 DeleteCommand
值后,相应的数据 Web 控件智能标记中的“启用插入”、“启用编辑”或“启用删除”选项将变为可用。 为了说明这一点,让我们从 Querying.aspx
使用 SqlDataSource 控件查询数据 教程中创建的页面为例,并将其扩充为包含删除功能。
首先,InsertUpdateDelete.aspx
从 SqlDataSource
文件夹中打开 和 Querying.aspx
页。 从页面上的DesignerQuerying.aspx
,从第一个示例中选择 SqlDataSource 和 GridView, (ProductsDataSource
和 GridView1
控件) 。 选择这两个控件后,转到“编辑”菜单,然后选择“复制 (”或只需按 Ctrl+C) 。 接下来,转到 的DesignerInsertUpdateDelete.aspx
并粘贴控件。 将两个控件 InsertUpdateDelete.aspx
移到 后,在浏览器中测试页面。 应会看到数据库表中所有记录Products
的 、 ProductName
和 UnitPrice
列的值ProductID
。
图 1:列出所有产品,按 ProductID
排序 (单击以查看全尺寸图像)
添加 SqlDataSource 的 DeleteCommand 和 DeleteParameters 属性
此时,我们有一个 SqlDataSource,它只返回表中的所有记录 Products
,以及一个呈现此数据的 GridView。 我们的目标是扩展此示例,以允许用户通过 GridView 删除产品。 为此,我们需要指定 SqlDataSource 控件 DeleteCommand
和 DeleteParameters
属性的值,然后将 GridView 配置为支持删除。
DeleteCommand
可以通过多种方式指定 和 DeleteParameters
属性:
- 通过声明性语法
- 从Designer中的属性窗口
- 从“配置数据源”向导中的“指定自定义 SQL 语句或存储过程”屏幕
- 通过“配置数据源”向导中视图屏幕中的“指定列”屏幕中的“高级”按钮,该按钮实际上将自动生成
DELETE
和DeleteParameters
属性中使用的DeleteCommand
SQL 语句和参数集合
我们将了解如何在步骤 2 中自动 DELETE
创建 语句。 现在,让我们使用Designer中的属性窗口,不过配置数据源向导或声明性语法选项同样可行。
在 中的DesignerInsertUpdateDelete.aspx
中,单击“ProductsDataSource
SqlDataSource”,然后从“视图”菜单中调出属性窗口 (,选择“属性窗口”,或直接点击 F4) 。 选择 DeleteQuery 属性,这将显示一组省略号。
图 2:从“属性”窗口中选择 DeleteQuery 属性
注意
SqlDataSource 没有 DeleteQuery 属性。 相反,DeleteQuery 是 和 DeleteParameters
属性的组合DeleteCommand
,仅在通过Designer查看窗口时在属性窗口中列出。 如果在“源”视图中查看属性窗口,则会改为找到 DeleteCommand
属性。
单击 DeleteQuery 属性中的省略号,打开“命令和参数编辑器”对话框, (请参阅图 3) 。 在此对话框中, DELETE
可以指定 SQL 语句并指定参数。 如果希望) ,请在命令文本框中输入以下查询 DELETE
, (手动或使用查询生成器:
DELETE FROM Products
WHERE ProductID = @ProductID
接下来,单击“刷新参数”按钮,将 @ProductID
参数添加到下面的参数列表中。
@ProductID 参数添加到 DELETE 命令参数列表。” />
图 3:从“属性”窗口中选择 DeleteQuery 属性 (单击以查看全尺寸图像)
不要为此参数提供值, (将其参数源保留为 None ) 。 向 GridView 添加删除支持后,GridView 将自动提供此参数值,使用单击 DataKeys
了“删除”按钮的行的集合值。
注意
查询中使用的 DELETE
参数名称 必须与 GridView、DetailsView 或 FormView 中的值的名称 DataKeyNames
相同。 也就是说,语句中的 DELETE
参数被有意命名 @ProductID
为 (而不是 @ID
) ,因为 Products 表中的主键列名称 (,因此 GridView) ProductID
中的 DataKeyNames 值为 。
如果参数名称和 DataKeyNames
值不匹配,GridView 无法自动为参数分配集合中的 DataKeys
值。
在“命令和参数编辑器”对话框中输入与删除相关的信息后,单击“确定”,然后转到“源”视图以检查生成的声明性标记:
<asp:SqlDataSource ID="ProductsDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
SelectCommand=
"SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products]"
DeleteCommand="DELETE FROM Products WHERE ProductID = @ProductID">
<DeleteParameters>
<asp:Parameter Name="ProductID" />
</DeleteParameters>
</asp:SqlDataSource>
请注意属性以及 DeleteCommand
<DeleteParameters>
节和名为 productID
的 Parameter 对象的添加。
配置 GridView 以删除
添加 属性后 DeleteCommand
,GridView 智能标记现在包含“启用删除”选项。 继续检查此复选框。 如 插入、更新和删除概述中所述,这会导致 GridView 添加 CommandField,其 ShowDeleteButton
属性设置为 True
。 如图 4 所示,通过浏览器访问页面时,会包含“删除”按钮。 通过删除某些产品来测试此页面。
图 4:每个 GridView 行现在都包含一个“删除”按钮 (单击以查看全尺寸图像)
单击“删除”按钮后,发生回发,GridView 为单击了“删除”按钮的行分配ProductID
DataKeys
参数集合值的值,并调用 SqlDataSource 方法Delete()
。 然后,SqlDataSource 控件连接到数据库并执行 DELETE
语句。 然后,GridView 会重新绑定到 SqlDataSource,返回并显示当前产品集, (不再包含刚删除的记录) 。
注意
由于 GridView 使用其 DataKeys
集合填充 SqlDataSource 参数,因此必须将 GridView 属性 DataKeyNames
设置为构成主键的列 () ,并且 SqlDataSource 返回 SelectCommand
这些列。 此外,请务必将 SqlDataSource 中的 DeleteCommand
参数名称设置为 @ProductID
。 DataKeyNames
如果未设置 属性或参数未命名 @ProductsID
,则单击“删除”按钮将导致回发,但实际上不会删除任何记录。
图 5 以图形方式描述了这种交互。 有关与插入、更新和从数据 Web 控件中删除关联的事件链的更详细讨论 ,请参阅检查与插入、更新和 删除关联的事件教程。
图 5:单击 GridView 中的“删除”按钮会调用 SqlDataSource s Delete()
方法
步骤 2:自动生成 INSERT
、 UPDATE
和 DELETE
语句
如步骤 1 所述,INSERT
UPDATE
可以通过属性窗口或控件声明性语法指定 、 和 DELETE
SQL 语句。 但是,此方法要求手动写出 SQL 语句,这可能单调且容易出错。 幸运的是,“配置数据源”向导提供了一个选项,用于INSERT
UPDATE
在使用“指定视图表中的列”屏幕时自动生成 、 和 DELETE
语句。
让我们探讨此自动生成选项。 将 DetailsView 添加到 中的Designer,InsertUpdateDelete.aspx
并将其ID
属性设置为 ManageProducts
。 接下来,从 DetailsView 智能标记中选择创建新的数据源,并创建名为 的 ManageProductsDataSource
SqlDataSource。
图 6:创建名为 ManageProductsDataSource
的新 SqlDataSource (单击以查看全尺寸图像)
在“配置数据源”向导中NORTHWINDConnectionString
,选择使用连接字符串并单击“下一步”。 在“配置选择语句”屏幕中,保留“指定表或视图中的列”单选按钮处于选中状态,然后从下拉列表中选择 Products
该表。 ProductID
从复选框列表中选择 、ProductName
、 UnitPrice
和 Discontinued
列。
图 7:使用 Products
表返回 ProductID
、 ProductName
、 UnitPrice
和 Discontinued
列 (单击以查看全尺寸图像)
若要基于所选表和列自动生成 INSERT
、 UPDATE
和 DELETE
语句,请单击“高级”按钮,检查“生成 INSERT
、 UPDATE
和 DELETE
语句”复选框。
图 8:选中“生成 INSERT
、 UPDATE
和 DELETE
语句”复选框
仅当所选表具有主键且主键列 (或) 列包含在返回的列列表中时,才能选中“生成 INSERT
、 UPDATE
和 DELETE
语句”复选框。 选中“生成 INSERT
、 UPDATE
和 DELETE
语句”复选框后,“使用乐观并发”复选框将扩充 WHERE
生成的 UPDATE
和 DELETE
语句中的子句,以提供乐观并发控制。 现在,请取消选中此复选框;我们将在下一教程中检查 SqlDataSource 控件的乐观并发性。
选中“生成 INSERT
、 UPDATE
和 DELETE
语句”复选框后,单击“确定”返回到“配置选择语句”屏幕,然后单击“下一步”,然后单击“完成”,以完成“配置数据源”向导。 完成向导后,Visual Studio 会将 BoundFields 添加到 DetailsView 的 ProductID
、 ProductName
和 列,并为 UnitPrice
该 Discontinued
列添加 CheckBoxField。 在 DetailsView 的智能标记中,检查“启用分页”选项,以便访问此页面的用户可以单步执行产品。 此外,请清除 DetailsView 和Width
Height
属性。
请注意,智能标记具有可用的“启用插入”、“启用编辑”和“启用删除”选项。 这是因为 SqlDataSource 包含其 InsertCommand
、 UpdateCommand
、 和 DeleteCommand
的值,如以下声明性语法所示:
<asp:DetailsView ID="ManageProducts" runat="server" AllowPaging="True"
AutoGenerateRows="False" DataKeyNames="ProductID"
DataSourceID="ManageProductsDataSource" EnableViewState="False">
<Fields>
<asp:BoundField DataField="ProductID" HeaderText="ProductID"
InsertVisible="False" ReadOnly="True" SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName"
SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
SortExpression="UnitPrice" />
<asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
SortExpression="Discontinued" />
</Fields>
</asp:DetailsView>
<asp:SqlDataSource ID="ManageProductsDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
DeleteCommand=
"DELETE FROM [Products] WHERE [ProductID] = @ProductID"
InsertCommand=
"INSERT INTO [Products] ([ProductName], [UnitPrice], [Discontinued])
VALUES (@ProductName, @UnitPrice, @Discontinued)"
SelectCommand=
"SELECT [ProductID], [ProductName], [UnitPrice], [Discontinued]
FROM [Products]"
UpdateCommand=
"UPDATE [Products] SET [ProductName] = @ProductName,
[UnitPrice] = @UnitPrice, [Discontinued] = @Discontinued
WHERE [ProductID] = @ProductID">
<DeleteParameters>
<asp:Parameter Name="ProductID" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="ProductName" Type="String" />
<asp:Parameter Name="UnitPrice" Type="Decimal" />
<asp:Parameter Name="Discontinued" Type="Boolean" />
<asp:Parameter Name="ProductID" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="ProductName" Type="String" />
<asp:Parameter Name="UnitPrice" Type="Decimal" />
<asp:Parameter Name="Discontinued" Type="Boolean" />
</InsertParameters>
</asp:SqlDataSource>
请注意 SqlDataSource 控件如何为其 、 UpdateCommand
和 DeleteCommand
属性自动设置InsertCommand
值。 和 UpdateCommand
属性中InsertCommand
引用的列集基于 语句中的SELECT
列。 也就是说,在 和 UpdateCommand
中InsertCommand
没有每个“产品”列,而是只指定 SelectCommand
(少ProductID
的列,省略这些列,因为它是一个IDENTITY
列,在编辑时无法更改其值,在插入) 时会自动分配该值。 此外,对于 、 UpdateCommand
和 属性中的每个InsertCommand
参数,、 UpdateParameters
和 DeleteCommand
DeleteParameters
集合中InsertParameters
都有相应的参数。
若要打开 DetailsView 的数据修改功能,检查智能标记中的“启用插入”、“启用编辑”和“启用删除”选项。 这会添加 CommandField,其 ShowInsertButton
、 ShowEditButton
和 ShowDeleteButton
属性设置为 True
。
在浏览器中访问页面,并记下 DetailsView 中包含的“编辑”、“删除”和“新建”按钮。 单击“编辑”按钮会将 DetailsView 转换为编辑模式,其中显示属性设置为 False
(默认) 为 TextBox 的每个 BoundFieldReadOnly
,并显示 CheckBoxField 作为复选框。
图 9:详细信息查看默认编辑界面 (单击以查看全尺寸图像)
同样,可以删除当前选定的产品或向系统添加新产品。 由于 语句 InsertCommand
仅适用于 ProductName
、 UnitPrice
和 Discontinued
列,其他列具有 NULL
数据库在插入时分配的默认值。 与 ObjectDataSource 一样,如果 InsertCommand
缺少任何不允许 NULL
且没有默认值的数据库表列,则尝试执行 INSERT
语句时将发生 SQL 错误。
注意
DetailsView 的插入和编辑接口缺乏任何类型的自定义或验证。 若要添加验证控件或自定义接口,需要将 BoundFields 转换为 TemplateFields。 有关详细信息,请参阅将 验证控件添加到编辑和插入接口 和 自定义数据修改接口 教程。
此外,请记住,对于更新和删除,DetailsView 使用当前产品 DataKey
值,仅当配置 属性时 DataKeyNames
,该值才存在。 如果编辑或删除似乎不起作用,请确保 DataKeyNames
已设置 属性。
自动生成 SQL 语句的限制
由于“生成 INSERT
”、“ UPDATE
和 DELETE
语句”选项仅在从表中选取列时可用,因此对于更复杂的查询,必须编写自己的 INSERT
、 UPDATE
和 DELETE
语句,就像我们在步骤 1 中所做的那样。 通常,SQL SELECT
语句使用 JOIN
从一个或多个查找表带回数据以进行显示 (例如在) 显示产品信息时带回 Categories
表 s CategoryName
字段。 同时,我们可能希望允许用户编辑、更新或将数据插入核心表 (Products
,在本例中) 。
INSERT
虽然可以手动输入 、 UPDATE
和 DELETE
语句,但请考虑以下省时提示。 最初设置 SqlDataSource,以便它仅从 Products
表中拉回数据。 使用“配置数据源”向导的“指定表或视图屏幕中的 INSERT
列”,以便可以自动生成 、 UPDATE
和 DELETE
语句。 然后,在完成向导后,选择从属性窗口 (配置 SelectQuery,或者返回到“配置数据源”向导,但使用“指定自定义 SQL 语句或存储过程”选项) 。 然后更新 SELECT
语句以包含 JOIN
语法。 此方法提供了自动生成的 SQL 语句的省时优势,并允许更自定义 SELECT
的语句。
自动生成 INSERT
、 UPDATE
和 DELETE
语句的另一个限制是 和 UPDATE
语句中的INSERT
列基于 语句返回的SELECT
列。 但是,我们可能需要更新或插入更多或更少的字段。 例如,在步骤 2 的示例中,也许我们希望 UnitPrice
将 BoundField 设置为只读。 在这种情况下,它不应显示在 中 UpdateCommand
。 或者,我们可能需要设置未显示在 GridView 中的表字段的值。 例如,在添加新记录时,我们可能需要将 QuantityPerUnit
值设置为 TODO 。
如果需要此类自定义项,则需要通过属性窗口、向导中的“指定自定义 SQL 语句或存储过程”选项或通过声明性语法手动进行。
注意
在数据 Web 控件中添加没有对应字段的参数时,请记住,需要以某种方式为这些参数值赋值。 这些值可以是:直接在 或 UpdateCommand
中InsertCommand
硬编码;可以来自某些预定义的源 (查询字符串、会话状态、页面上的 Web 控件等) ;也可以以编程方式分配,如前面的教程所示。
总结
为了使数据 Web 控件能够利用其内置的插入、编辑和删除功能,它们绑定到的数据源控件必须提供此类功能。 对于 SqlDataSource,这意味着 INSERT
必须将 、 UPDATE
和 DELETE
SQL 语句分配给 InsertCommand
、 UpdateCommand
和 DeleteCommand
属性。 这些属性和相应的参数集合可以手动添加,也可以通过“配置数据源”向导自动生成。 在本教程中,我们研究了这两种技术。
我们在实现乐观并发教程中检查了如何通过 ObjectDataSource 使用 乐观并发 。 SqlDataSource 控件还提供乐观并发支持。 如步骤 2 中所述,在 INSERT
自动生成 、 UPDATE
和 DELETE
语句时,向导将提供“使用乐观并发”选项。 正如我们在下一篇教程中看到的,对 SqlDataSource 使用乐观并发会WHERE
修改 和 DELETE
语句中的 UPDATE
子句,以确保自上次在页面上显示数据以来其他列的值未更改。
编程快乐!
关于作者
斯科特·米切尔是七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自 1998 年以来一直在使用 Microsoft Web 技术。 Scott 担任独立顾问、培训师和作家。 他的最新一本书是 山姆斯在 24 小时内 ASP.NET 2.0。 可以在 上mitchell@4GuysFromRolla.com联系他,也可以通过他的博客(可在 中找到http://ScottOnWriting.NET)。