使用 SqlDataSource 插入、更新和刪除資料 (VB)

作者: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 控件值等等) ,或可以程序設計方式指派。 當 SqlDataSource 控制項的 Select() 方法以程式設計方式或自動從資料 Web 控制項叫用資料庫時,就會將參數值指派給查詢,而命令會從資料庫開始。 然後,結果會傳回為 DataSet 或 DataReader,視控件 s DataSourceMode 屬性的值而定。

除了選取數據之外,SqlDataSource 控制件也可以用來以非常相同的方式提供 INSERTUPDATE和 SQL 語句來插入、更新和 DELETE 刪除數據。 只要指派 InsertCommandUpdateCommand、 和 DeleteCommand 屬性 INSERT,即可執行、 UPDATEDELETE SQL 語句。 如果語句具有參數 (,因為其一律會) ,請在 、 UpdateParametersDeleteParameters 集合中包含InsertParameters參數。

指定 InsertCommandUpdateCommandDeleteCommand 值之後,對應資料 Web 控制項智慧標記中的 [啟用插入]、[啟用編輯] 或 [啟用刪除] 選項將會變成可用。 為了說明這點,讓我們從 Querying.aspx 我們在 使用 SqlDataSource 控件查詢數據 教學課程中建立的頁面取得範例,並加以增強以包含刪除功能。

首先,InsertUpdateDelete.aspxSqlDataSource 資料夾開啟 和 Querying.aspx 頁面。 從頁面上的 DesignerQuerying.aspx,從第一個範例中選取 SqlDataSource 和 GridView (ProductsDataSourceGridView1 控件) 。 選取兩個控件之後,請移至 [編輯] 功能表,然後選擇 [複製 (或只按 Ctrl+C) 。 接下來,移至 的 InsertUpdateDelete.aspx Designer 並貼上控件。 將兩個控件 InsertUpdateDelete.aspx移至 之後,請在瀏覽器中測試頁面。 您應該會看到資料庫資料表中Products所有記錄的ProductIDProductNameUnitPrice 資料行的值。

所有產品都會列出,依 ProductID 排序

圖 1:列出所有產品,依 ProductID (按兩下以檢視完整大小的影像)

新增 SqlDataSource 的 DeleteCommand 和 DeleteParameters 屬性

此時,我們有一個 SqlDataSource,只要從 Products 數據表傳回所有記錄,以及轉譯此數據的 GridView 即可。 我們的目標是擴充此範例,以允許使用者透過 GridView 刪除產品。 若要達成此目的,我們需要指定 SqlDataSource 控件的值 DeleteCommandDeleteParameters 屬性,然後設定 GridView 以支持刪除。

DeleteCommandDeleteParameters 屬性可以透過數種方式來指定:

  • 透過宣告式語法
  • 從 Designer中的 屬性視窗
  • 從 [設定數據源精靈] 中的 [指定自定義 SQL 語句或預存程式] 畫面
  • 透過 [設定數據源精靈] 中 [從檢視表指定數據行] 畫面中的 [進階] 按鈕,這實際上會自動產生 DELETEDeleteParameters 屬性中使用的 DeleteCommand SQL 語句和參數集合

我們將檢查如何在步驟 2 中自動 DELETE 建立 語句。 現在,讓我們在 Designer 中使用 屬性視窗,雖然 [設定數據源精靈] 或宣告式語法選項也可以運作。

從中的 InsertUpdateDelete.aspxDesigner 中,單擊 ProductsDataSource [SqlDataSource],然後從 [檢視] 功能表顯示 屬性視窗 (、選擇 [屬性視窗],或直接點擊 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 相同。 也就是說,語句中的 參數會以目的方式命名 @ProductID (,而不是例如 @ID ,) ,因為 Products 數據表中的DELETE主鍵數據行名稱 (,因此 GridView) 中的 DataKeyNames 值是 ProductID

如果參數名稱和 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 會 ProductID 為單擊 [刪除] 按鈕的數據列指派集合值的參數 DataKeys ,並叫用 SqlDataSource s Delete() 方法。 然後,SqlDataSource 控制項會連接到資料庫並執行 DELETE 語句。 GridView 接著會重新系結至 SqlDataSource,並返回並顯示目前的產品集, (不再包含剛刪除的記錄) 。

注意

由於 GridView 使用其 DataKeys 集合來填入 SqlDataSource 參數,因此 GridView DataKeyNames 的 屬性必須設定為構成主鍵的數據行 () ,而且 SqlDataSource 會 SelectCommand 傳回這些數據行。 此外,請務必將 SqlDataSource s DeleteCommand 中的參數名稱設定為 @ProductIDDataKeyNames如果未設定屬性,或未命名 @ProductsID參數,請按兩下 [刪除] 按鈕會導致回傳,但實際上不會刪除任何記錄。

圖 5 以圖形方式描述此互動。 請參閱 檢查與插入、更新和刪除相關聯的事件 教學課程,以取得與插入、更新及刪除數據 Web 控件相關聯之事件鏈結的更詳細討論。

按兩下 GridView 中的 [刪除] 按鈕會叫用 SqlDataSource s Delete () 方法

圖 5:按兩下 GridView 中的 [刪除] 按鈕會叫用 SqlDataSource s Delete() 方法

步驟 2:自動產生 INSERTUPDATEDELETE 語句

如步驟 1 所檢查,INSERT可以透過 屬性視窗 或控件的宣告式語法來指定 、 UPDATEDELETE SQL 語句。 不過,這種方法需要手動寫出 SQL 語句,這可以是單調且容易出錯的。 幸運的是,[設定數據源精靈] 提供一個選項,可讓您 INSERT在使用檢視表畫面中的 [指定數據行] 時自動產生 、 UPDATEDELETE 語句。

讓我們來探索這個自動產生選項。 將 DetailsView 新增至 中的 InsertUpdateDelete.aspx Designer,並將其 ID 屬性設定為 ManageProducts。 接下來,從 DetailsView 的智慧標記中,選擇建立新的數據源,並建立名為 的 ManageProductsDataSourceSqlDataSource。

建立名為 ManageProductsDataSource 的新 SqlDataSource

圖 6:建立名為 ManageProductsDataSource 的新 SqlDataSource (按兩下即可檢視大小完整的映像)

從 [設定數據源精靈] 中,選擇使用 NORTHWINDConnectionString 連接字串,然後按 [下一步]。 從 [設定選取語句] 畫面,將 [從數據表或檢視] 單選按鈕保留 [指定數據行],然後從下拉式清單中挑選 Products 數據表。 ProductID從複選框清單中選取、 ProductNameUnitPriceDiscontinued 資料行。

使用 Products 數據表,傳回 ProductID、ProductName、UnitPrice 和已停止的數據行

圖 7:使用 Products 數據表,傳回 ProductIDProductNameUnitPriceDiscontinued 資料行 (按鍵即可檢視大小完整的影像)

若要根據選取的數據表和數據行自動產生 INSERTUPDATEDELETE 語句,請按兩下 [進階] 按鈕並核取 [產生 INSERTUPDATEDELETE 語句] 複選框。

核取 [產生 INSERT、UPDATE 和 DELETE 語句] 複選框

圖 8:核取 [產生 INSERTUPDATEDELETE 語句] 複選框

只有在選取的數據表具有主鍵,且主鍵數據行 (或數據行) 包含在傳回的數據行清單中時,才會核取 [產生 INSERTUPDATEDELETE 語句] 複選框。 選取 [產生 INSERTUPDATE和 語句] 複選框后,[使用開放式並行存取] 複選框會變成可選取的複選框,將會增強WHERE產生的 UPDATEDELETEDELETE 語句中的 子句,以提供開放式並行控制。 現在,將此複選框保持未核取;我們將在下一個教學課程中使用 SqlDataSource 控件來檢查開放式並行存取。

核取 [產生 INSERTUPDATEDELETE 語句] 複選框之後,按兩下 [確定] 傳回 [設定選取語句] 畫面,然後按 [下一步],然後按下 [完成],以完成 [設定數據源精靈]。 完成精靈時,Visual Studio 會將 BoundFields 新增至 、 ProductNameUnitPrice 數據行的 ProductIDDetailsView,以及數據行的 Discontinued CheckBoxField。 從 DetailsView 的智慧標記中,核取 [啟用分頁] 選項,讓使用者瀏覽此頁面可以逐步執行產品。 同時清除DetailsView的 WidthHeight 屬性。

請注意,智慧標記具有 [啟用插入]、[啟用編輯] 和 [啟用刪除] 選項可用。 這是因為 SqlDataSource 包含其 InsertCommandUpdateCommandDeleteCommand的值,如下列宣告式語法所示:

<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 控制項如何針對其 InsertCommandUpdateCommandDeleteCommand 屬性自動設定值。 和 UpdateCommand 屬性中所InsertCommand參考的數據行集合是以 語句中的數據SELECT行為基礎。 也就是說,除了 和UpdateCommand中的每個 InsertCommandProducts 數據行之外,也只會省略 (ProductID中指定的SelectCommand數據行,因為它是一個IDENTITY數據行,其值無法在編輯時變更,而且在插入) 時會自動指派。 此外,針對、 UpdateCommand和屬性中的每個InsertCommand參數,、 和 DeleteParameters 集合中有InsertParametersUpdateParameters對應的DeleteCommand參數。

若要開啟 DetailsView 的數據修改功能,請檢查智慧標記中的 [啟用插入]、[啟用編輯] 和 [啟用刪除] 選項。 這會新增 CommandField,其ShowInsertButtonShowEditButton、 和 ShowDeleteButton 屬性設定為 True

瀏覽瀏覽器中的頁面,並記下 DetailsView 中包含的 [編輯]、[刪除] 和 [新增] 按鈕。 按兩下 [編輯] 按鈕會將DetailsView轉換成編輯模式,其中顯示每個 BoundField ReadOnly 屬性設定 False 為 (預設) 為 TextBox,以及 CheckBoxField 做為複選框。

DetailsView 的默認編輯介面

圖 9:D etailsView 的預設編輯介面 (按兩下即可檢視大小完整的影像)

同樣地,您可以刪除目前選取的產品,或將新產品新增至系統。 InsertCommand由於語句只適用於ProductNameUnitPriceDiscontinued 數據行,因此其他數據行在插入時,資料庫會指派NULL其預設值。 就像 ObjectDataSource 一樣,如果 InsertCommand 遺漏任何不允許 NULL 且沒有預設值的資料庫數據表數據行,則嘗試執行 INSERT 語句時會發生 SQL 錯誤。

注意

DetailsView 的插入和編輯介面缺少任何類型的自定義或驗證。 若要新增驗證控件或自定義介面,您必須將 BoundFields 轉換為 TemplateFields。 如需詳細資訊 ,請參閱將驗證控件新增至編輯和插入介面自定義數據修改介面 教學課程。

此外,請記住,若要更新和刪除,DetailsView 會使用目前的產品 DataKey 值,只有在設定屬性時 DataKeyNames 才會存在。 如果編輯或刪除似乎沒有任何作用,請確定 DataKeyNames 已設定 屬性。

自動產生 SQL 語句的限制

由於只有在從數據表挑選數據行時,才能使用 [產生 INSERTUPDATEDELETE 語句] 選項,因此針對更複雜的查詢,您必須撰寫自己的 INSERTUPDATEDELETE 語句,就像我們在步驟 1 中所做的一樣。 通常,SQL SELECT 語句會使用 JOIN 來從一或多個查閱數據表傳回數據,以供顯示 (,例如在顯示產品資訊時將數據表CategoryName字段帶回 Categories) 。 同時,我們可能會想要允許使用者編輯、更新或將數據插入核心數據表 (Products,在此情況下) 。

INSERT雖然 可以手動輸入 、 UPDATEDELETE 語句,但請考慮下列省時提示。 一開始設定 SqlDataSource,讓它只從 Products 數據表提取數據。 使用 [設定數據源精靈] 的 [從數據表或檢視畫面指定數據行],以便自動產生 INSERTUPDATEDELETE 語句。 然後,完成精靈之後,選擇從 屬性視窗 (設定 SelectQuery,或者返回 [設定數據源精靈],但使用 [指定自定義 SQL 語句或預存程式] 選項) 。 然後更新 SELECT 語句以包含 JOIN 語法。 這項技術提供自動產生之 SQL 語句的省時優點,並允許更自定義 SELECT 的語句。

自動產生INSERTUPDATE和語句的另一個限制是 和 DELETEUPDATE 語句中的數據INSERT行是以語句所傳回的數據SELECT行為基礎。 不過,您可能需要更新或插入更多或較少的欄位。 例如,在步驟 2 的範例中,或許我們想要讓 UnitPrice BoundField 成為只讀的。 在此情況下,它不應該出現在 中 UpdateCommand。 或者,我們可能會想要設定未出現在 GridView 中的數據表欄位值。 例如,新增記錄時,我們可能會想要將 QuantityPerUnit 值設定為 TODO 。

如果需要這類自定義,您必須透過 屬性視窗、在精靈中指定自定義 SQL 語句或預存程式選項,或透過宣告式語法手動進行自定義。

注意

在數據 Web 控制件中新增沒有對應欄位的參數時,請記住,這些參數值必須以某種方式指派值。 這些值可以是:直接在 或 UpdateCommandInsertCommand編碼;可以來自某些預先定義的來源, (查詢字串、會話狀態、頁面上的 Web 控件等等) ;或者可以程式設計方式指派,如上一個教學課程中所見。

摘要

為了讓數據 Web 控制項利用其內建的插入、編輯和刪除功能,他們系結的數據源控件必須提供這類功能。 針對 SqlDataSource,這表示 INSERT必須將、 UPDATEDELETE SQL 語句指派給 InsertCommandUpdateCommandDeleteCommand 屬性。 這些屬性和對應的參數集合可以透過 [設定數據源精靈] 手動新增或自動產生。 在本教學課程中,我們已檢查這兩種技術。

我們已在 實作開放式並行 存取教學課程中,使用開放式並行存取搭配 ObjectDataSource 來檢查。 SqlDataSource 控制件也提供開放式並行支援。 如步驟 2 所述,當自動產生 INSERTUPDATEDELETE 語句時,精靈會提供 [使用開放式並行存取] 選項。 如下一個教學課程所示,搭配 SqlDataSource 使用開放式並行存取會修改 WHEREDELETE 語句中的 UPDATE 子句,以確保自從上次顯示數據之後,其他數據行的值尚未變更。

快樂的程序設計!

關於作者

Scott Mitchell 是七份 ASP/ASP.NET 書籍的作者,以及 1998 年以來與 Microsoft Web 技術合作的 4GuysFromRolla.com 作者。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET