使用 SqlDataSource 插入、更新和删除数据 (C#)

作者 :Scott Mitchell

下载 PDF

在前面的教程中,我们了解了 ObjectDataSource 控件如何允许插入、更新和删除数据。 SqlDataSource 控件支持相同的操作,但方法不同,本教程演示如何配置 SqlDataSource 以插入、更新和删除数据。

简介

插入、更新和删除概述中所述,GridView 控件提供内置的更新和删除功能,而 DetailsView 和 FormView 控件包括插入支持以及编辑和删除功能。 这些数据修改功能可以直接插入数据源控件,而无需编写代码行。 使用 ObjectDataSource 检查插入、更新和删除概述,以方便使用 GridView、DetailsView 和 FormView 控件进行插入、更新和删除。 或者,可以使用 SqlDataSource 代替 ObjectDataSource。

回想一下,为了支持插入、更新和删除,需要使用 ObjectDataSource 指定要调用的对象层方法来执行插入、更新或删除操作。 使用 SqlDataSource 时,我们需要提供 INSERTUPDATEDELETE SQL 语句, (或存储过程) 执行。 如本教程所示,这些语句可以手动创建,也可以由 SqlDataSource 的“配置数据源”向导自动生成。

注意

由于我们已经讨论了 GridView、DetailsView 和 FormView 控件的插入、编辑和删除功能,本教程将重点介绍如何配置 SqlDataSource 控件以支持这些操作。 如果需要深入了解如何在 GridView、DetailsView 和 FormView 中实现这些功能,请从插入、更新和删除概述开始,返回到编辑、插入 和删除数据教程。

步骤 1:指定 INSERT、UPDATE 和 DELETE 语句

正如我们在过去两个教程中看到的,若要从 SqlDataSource 控件检索数据,需要设置两个属性:

  1. ConnectionString,它指定要将查询发送到哪个数据库,以及
  2. SelectCommand,指定要执行以返回结果的即席 SQL 语句或存储过程名称。

对于 SelectCommand 具有参数的值,参数值通过 SqlDataSource 集合 SelectParameters 指定,可以包括硬编码值、常见参数源值 (查询字符串字段、会话变量、Web 控件值等) ,也可以以编程方式分配。 以编程方式或从数据 Web 控件自动调用 SqlDataSource 控件 方法 Select() 时,会建立与数据库的连接,将参数值分配给查询,并将命令传递到数据库。 然后,根据控件 属性 DataSourceMode 的值,以 DataSet 或 DataReader 的形式返回结果。

除了选择数据之外,SqlDataSource 控件还可以通过以大致相同的方式提供 INSERTUPDATE和 SQL 语句来插入、更新和 DELETE 删除数据。 只需为 、 和 属性INSERT分配要执行的 、 UPDATEDELETE SQL DeleteCommand 语句。 UpdateCommandInsertCommand 如果语句具有 (参数,因为它们将始终) ,请将它们包含在 、 UpdateParametersDeleteParameters 集合中InsertParameters

InsertCommand指定 、 UpdateCommandDeleteCommand 值后,相应的数据 Web 控件智能标记中的“启用插入”、“启用编辑”或“启用删除”选项将变为可用。 为了说明这一点,让我们从 Querying.aspx 使用 SqlDataSource 控件查询数据 教程中创建的页面为例,并将其扩充为包含删除功能。

首先,InsertUpdateDelete.aspxSqlDataSource 文件夹中打开 和 Querying.aspx 页。 从页面上的DesignerQuerying.aspx,从第一个示例中选择 SqlDataSource 和 GridView, (ProductsDataSourceGridView1 控件) 。 选择这两个控件后,转到“编辑”菜单,然后选择“复制 (”或只需按 Ctrl+C) 。 接下来,转到 的DesignerInsertUpdateDelete.aspx并粘贴控件。 将两个控件 InsertUpdateDelete.aspx移到 后,在浏览器中测试页面。 应会看到数据库表中所有记录Products的 、 ProductNameUnitPrice 列的值ProductID

列出所有产品,按 ProductID 排序

图 1:列出所有产品,按 ProductID 排序 (单击以查看全尺寸图像)

添加 SqlDataSource 的 DeleteCommand 和 DeleteParameters 属性

此时,我们有一个 SqlDataSource,它只返回表中的所有记录 Products ,以及一个呈现此数据的 GridView。 我们的目标是扩展此示例,以允许用户通过 GridView 删除产品。 为此,我们需要指定 SqlDataSource 控件 DeleteCommandDeleteParameters 属性的值,然后将 GridView 配置为支持删除。

DeleteCommand可以通过多种方式指定 和 DeleteParameters 属性:

  • 通过声明性语法
  • 从Designer中的属性窗口
  • 从“配置数据源”向导中的“指定自定义 SQL 语句或存储过程”屏幕
  • 通过“配置数据源”向导中视图屏幕中的“指定列”屏幕中的“高级”按钮,该按钮实际上将自动生成 DELETEDeleteParameters 属性中使用的 DeleteCommand SQL 语句和参数集合

我们将了解如何在步骤 2 中自动 DELETE 创建 语句。 现在,让我们使用Designer中的属性窗口,不过配置数据源向导或声明性语法选项同样可行。

在 中的DesignerInsertUpdateDelete.aspx中,单击“ProductsDataSourceSqlDataSource”,然后从“视图”菜单中调出属性窗口 (,选择“属性窗口”,或直接点击 F4) 。 选择 DeleteQuery 属性,这将显示一组省略号。

显示 ProductsDataSource 属性窗口的屏幕截图,其中选择了 DeleteQuery 属性。

图 2:从“属性”窗口中选择 DeleteQuery 属性

注意

SqlDataSource 没有 DeleteQuery 属性。 相反,DeleteQuery 是 和 DeleteParameters 属性的组合DeleteCommand,仅在通过Designer查看窗口时在属性窗口中列出。 如果在“源”视图中查看属性窗口,则会改为找到 DeleteCommand 属性。

单击 DeleteQuery 属性中的省略号,打开“命令和参数编辑器”对话框, (请参阅图 3) 。 在此对话框中, DELETE 可以指定 SQL 语句并指定参数。 如果希望) ,请在命令文本框中输入以下查询 DELETE , (手动或使用查询生成器:

DELETE FROM Products
WHERE ProductID = @ProductID

接下来,单击“刷新参数”按钮,将 @ProductID 参数添加到下面的参数列表中。

显示“命令和参数编辑器”窗口的屏幕截图,其中 <span class=@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 所示,通过浏览器访问页面时,会包含“删除”按钮。 通过删除某些产品来测试此页面。

每个 GridView 行现在包括一个“删除”按钮

图 4:每个 GridView 行现在都包含一个“删除”按钮 (单击以查看全尺寸图像)

单击“删除”按钮后,发生回发,GridView 为单击了“删除”按钮的行分配ProductIDDataKeys参数集合值的值,并调用 SqlDataSource 方法Delete()。 然后,SqlDataSource 控件连接到数据库并执行 DELETE 语句。 然后,GridView 会重新绑定到 SqlDataSource,返回并显示当前产品集, (不再包含刚删除的记录) 。

注意

由于 GridView 使用其 DataKeys 集合填充 SqlDataSource 参数,因此必须将 GridView 属性 DataKeyNames 设置为构成主键的列 () ,并且 SqlDataSource 返回 SelectCommand 这些列。 此外,请务必将 SqlDataSource 中的 DeleteCommand 参数名称设置为 @ProductIDDataKeyNames如果未设置 属性或参数未命名 @ProductsID,则单击“删除”按钮将导致回发,但实际上不会删除任何记录。

图 5 以图形方式描述了这种交互。 有关与插入、更新和从数据 Web 控件中删除关联的事件链的更详细讨论 ,请参阅检查与插入、更新和 删除关联的事件教程。

单击 GridView 中的“删除”按钮会调用 SqlDataSource 的 Delete () 方法

图 5:单击 GridView 中的“删除”按钮会调用 SqlDataSource s Delete() 方法

步骤 2:自动生成 INSERT、UPDATE 和 DELETE 语句

如步骤 1 所述,INSERTUPDATE可以通过属性窗口或控件声明性语法指定 、 和 DELETE SQL 语句。 但是,此方法要求手动写出 SQL 语句,这可能单调且容易出错。 幸运的是,“配置数据源”向导提供了一个选项,用于INSERTUPDATE在使用“指定视图表中的列”屏幕时自动生成 、 和 DELETE 语句。

让我们探索此自动生成选项。 将 DetailsView 添加到 中的Designer,InsertUpdateDelete.aspx并将其ID属性设置为 ManageProducts。 接下来,从 DetailsView 智能标记中选择创建新的数据源,并创建名为 的 ManageProductsDataSourceSqlDataSource。

创建新的 SqlDataSource Named ManageProductsDataSource

图 6:创建名为 ManageProductsDataSource 的新 SqlDataSource (单击以查看全尺寸图像)

在“配置数据源”向导中NORTHWINDConnectionString,选择使用连接字符串并单击“下一步”。 在“配置选择语句”屏幕中,保留“指定表或视图中的列”单选按钮处于选中状态,然后从下拉列表中选择 Products 该表。 ProductID从复选框列表中选择 、ProductNameUnitPriceDiscontinued 列。

使用 Products 表返回 ProductID、ProductName、UnitPrice 和已停用列

图 7:使用 Products 表返回 ProductIDProductNameUnitPriceDiscontinued 列 (单击以查看全尺寸图像)

若要基于所选表和列自动生成 INSERTUPDATEDELETE 语句,请单击“高级”按钮,检查“生成 INSERTUPDATEDELETE 语句”复选框。

选中“生成 INSERT、UPDATE 和 DELETE 语句”复选框

图 8:选中“生成 INSERTUPDATEDELETE 语句”复选框

仅当所选表具有主键且主键列 (或) 列包含在返回的列列表中时,才能选中“生成 INSERTUPDATEDELETE 语句”复选框。 选中“生成 INSERTUPDATEDELETE 语句”复选框后,“使用乐观并发”复选框将扩充 WHERE 生成的 UPDATEDELETE 语句中的子句,以提供乐观并发控制。 现在,请取消选中此复选框;我们将在下一教程中检查 SqlDataSource 控件的乐观并发性。

选中“生成 INSERTUPDATEDELETE 语句”复选框后,单击“确定”返回到“配置选择语句”屏幕,然后单击“下一步”,然后单击“完成”,以完成“配置数据源”向导。 完成向导后,Visual Studio 会将 BoundFields 添加到 DetailsView 的 ProductIDProductName和 列,并为 UnitPriceDiscontinued 列添加 CheckBoxField。 在 DetailsView 的智能标记中,检查“启用分页”选项,以便访问此页面的用户可以单步执行产品。 此外,请清除 DetailsView 和WidthHeight属性。

请注意,智能标记具有可用的“启用插入”、“启用编辑”和“启用删除”选项。 这是因为 SqlDataSource 包含其 InsertCommandUpdateCommand、 和 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 控件如何为其 、 UpdateCommandDeleteCommand 属性自动设置InsertCommand值。 和 UpdateCommand 属性中InsertCommand引用的列集基于 语句中的SELECT列。 也就是说,在 和 UpdateCommandInsertCommand没有每个“产品”列,而是只指定 SelectCommand (少ProductID的列,省略这些列,因为它是一个IDENTITY,在编辑时无法更改其值,在插入) 时会自动分配该值。 此外,对于 、 UpdateCommand和 属性中的每个InsertCommand参数,、 UpdateParametersDeleteCommandDeleteParameters 集合中InsertParameters都有相应的参数。

若要打开 DetailsView 的数据修改功能,检查智能标记中的“启用插入”、“启用编辑”和“启用删除”选项。 这会添加 CommandField,其 ShowInsertButtonShowEditButtonShowDeleteButton 属性设置为 true

在浏览器中访问页面,并记下 DetailsView 中包含的“编辑”、“删除”和“新建”按钮。 单击“编辑”按钮会将 DetailsView 转换为编辑模式,其中显示属性设置为 false (默认) 为 TextBox 的每个 BoundFieldReadOnly,并显示 CheckBoxField 作为复选框。

DetailsView s 默认编辑界面

图 9:详细信息查看默认编辑界面 (单击以查看全尺寸图像)

同样,可以删除当前选定的产品或向系统添加新产品。 由于 语句 InsertCommand 仅适用于 ProductNameUnitPriceDiscontinued 列,其他列具有 NULL 数据库在插入时分配的默认值。 与 ObjectDataSource 一样,如果 InsertCommand 缺少任何不允许 NULL 且没有默认值的数据库表列,则尝试执行 INSERT 语句时将发生 SQL 错误。

注意

DetailsView 的插入和编辑接口缺乏任何类型的自定义或验证。 若要添加验证控件或自定义接口,需要将 BoundFields 转换为 TemplateFields。 有关详细信息,请参阅将 验证控件添加到编辑和插入接口自定义数据修改接口 教程。

此外,请记住,对于更新和删除,DetailsView 使用当前产品 DataKey 值,仅当配置 属性时 DataKeyNames ,该值才存在。 如果编辑或删除似乎不起作用,请确保 DataKeyNames 已设置 属性。

自动生成 SQL 语句的限制

由于“生成 INSERT”、“ UPDATEDELETE 语句”选项仅在从表中选取列时可用,因此对于更复杂的查询,必须编写自己的 INSERTUPDATEDELETE 语句,就像我们在步骤 1 中所做的那样。 通常,SQL SELECT 语句使用 JOIN 从一个或多个查找表带回数据以进行显示 (例如在) 显示产品信息时带回 Categories 表 s CategoryName 字段。 同时,我们可能希望允许用户编辑、更新或将数据插入核心表 (Products,在本例中) 。

INSERT虽然可以手动输入 、 UPDATEDELETE 语句,但请考虑以下省时提示。 最初设置 SqlDataSource,以便它仅从 Products 表中拉回数据。 使用“配置数据源”向导的“指定表或视图屏幕中的 INSERT列”,以便可以自动生成 、 UPDATEDELETE 语句。 然后,在完成向导后,选择从属性窗口 (配置 SelectQuery,或者返回到“配置数据源”向导,但使用“指定自定义 SQL 语句或存储过程”选项) 。 然后更新 SELECT 语句以包含 JOIN 语法。 此方法提供了自动生成的 SQL 语句的省时优势,并允许更自定义 SELECT 的语句。

自动生成 INSERTUPDATEDELETE 语句的另一个限制是 和 UPDATE 语句中的INSERT列基于 语句返回的SELECT列。 但是,我们可能需要更新或插入更多或更少的字段。 例如,在步骤 2 的示例中,也许我们希望 UnitPrice 将 BoundField 设置为只读。 在这种情况下,它不应显示在 中 UpdateCommand。 或者,我们可能需要设置未显示在 GridView 中的表字段的值。 例如,在添加新记录时,我们可能需要将 QuantityPerUnit 值设置为 TODO 。

如果需要此类自定义项,则需要通过属性窗口、向导中的“指定自定义 SQL 语句或存储过程”选项或通过声明性语法手动进行。

注意

在数据 Web 控件中添加没有对应字段的参数时,请记住,需要以某种方式为这些参数值赋值。 这些值可以是:直接在 或 UpdateCommandInsertCommand硬编码;可以来自某些预定义的源 (查询字符串、会话状态、页面上的 Web 控件等) ;也可以以编程方式分配,如前面的教程所示。

总结

为了使数据 Web 控件能够利用其内置的插入、编辑和删除功能,它们绑定到的数据源控件必须提供此类功能。 对于 SqlDataSource,这意味着 INSERT必须将 、 UPDATEDELETE SQL 语句分配给 InsertCommandUpdateCommandDeleteCommand 属性。 这些属性和相应的参数集合可以手动添加,也可以通过“配置数据源”向导自动生成。 在本教程中,我们研究了这两种技术。

我们在实现乐观并发教程中检查了如何通过 ObjectDataSource 使用 乐观并发 。 SqlDataSource 控件还提供乐观并发支持。 如步骤 2 中所述,在 INSERT自动生成 、 UPDATEDELETE 语句时,向导将提供“使用乐观并发”选项。 正如我们在下一篇教程中看到的,对 SqlDataSource 使用乐观并发会WHERE修改 和 DELETE 语句中的 UPDATE 子句,以确保自上次在页面上显示数据以来其他列的值未更改。

编程快乐!

关于作者

斯科特·米切尔是七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自 1998 年以来一直在使用 Microsoft Web 技术。 Scott 担任独立顾问、培训师和作家。 他的最新一本书是 山姆斯在 24 小时内 ASP.NET 2.0。 可以在 上mitchell@4GuysFromRolla.com联系他,也可以通过他的博客(可在 中找到http://ScottOnWriting.NET)。