asp.net|建立|訪問|資料
第四步:插入,更新和刪除資料
常用的插入,更新和刪除資料的模式有兩種。第一種模式,我稱之為DB直接模式,涉及的方法被調用時,會向資料庫裡發出一個INSERT, 或UPDATE,或DELETE命令,這個命令只對單個資料庫記錄做操作。象這樣的方法一般接受一系列對應於插入,更新或刪除的值的標量參數(譬如整數,字串,布爾值,日期時間等)。譬如,用這個模式來操作Products表的話,刪除方法會接受一個整數參數,代表所需要刪除的記錄的ProductID,而插入方法則會接受一個對應於ProductName的字串,對應 於UnitPrice的decimal值,對應於UnitsOnStock的整數等等。
圖 21: 每個插入,更新,和刪除請求都被立刻發送到資料庫
另外一個模式,我稱之為批更新模式,可以在一個方法調用裡更新整個DataSet,或者整個DataTable,或 者一個DataRow集合。在這個模式裡,開發人員在一個DataTable中刪除,插入,修改DataRow,然後把這 些DataRow或整個DataTable傳給一個更新方法。然後這個方法會輪循傳入的DataRow們,通過DataRow的RowState屬 性屬性來決定這些DataRow是否被改動過,或是新記錄,或是被刪除的記錄,然後為每個記錄發出合適的 資料庫命令。
圖 22: 在Update 方法調用之後,所有的變動都與資料庫同步了
在預設情形下,TableAdapter採用批更新模式,但也支援DB直接模式。因為我們在建立我們的TableAdapter時的進階選項中選擇了“產生插入,更新,和刪除語句” 這個選項,ProductsTableAdapter 包含了一個 Update()方法,該方法實現了批 更新模式。具體地說,TableAdapter包含了一個Update()<昀敳獴搨 ???oЁCODE> 方法,可以傳入一個強型別 的DataSet,或者一個強型別的DataTable,或者一個和多個DataRow。假如你在一開始建立TableAdapter時的選項中沒有清除“產生DB直接方法(GenerateDBDirectMethods)”複選框的話,DB直接模 式也會通過Insert(),Update()和Delete()方法來實現。
這兩種資料修改模式都使用 了TableAdapter的InsertCommand,UpdateCommand, 和DeleteCommand屬性來向資料庫發出對應 的INSERT,UPDATE和DELETE命令。你可以在DataSet設計器裡點擊TableAdapter,然後在屬性視窗查看和改 動InsertCommand,UpdateCommand, 和DeleteCommand屬性。(確 認你選擇了TableAdapter,並且ProductsTableAdapter對象是屬性視窗中下拉框裡被選中的項)
圖23: TableAdapter包含InsertCommand,UpdateCommand, 和DeleteCommand等屬性
想查看或改動這些資料庫命令的屬性的話,點擊CommandText子屬性,這會啟動對應的查詢 產生器。
圖 24: 在查詢產生器裡配置插入,更新,刪除語句
下面的編碼例子示範了如何使用批更新模式來把沒被終止的,且庫存等於或少於25個單元的產品的價格加 倍:
C# |
1 2 3 4 5 6 7 8 9 10 11 12 |
NorthwindTableAdapters.ProductsTableAdapter productsAdapter = new NorthwindTableAdapters.ProductsTableAdapter(); // For each product, double its price if it is not discontinued and // there are 25 items in stock or less Northwind.ProductsDataTable products = productsAdapter.GetProducts(); foreach (Northwind.ProductsRow product in products) if (!product.Discontinued && product.UnitsInStock <= 25) product.UnitPrice *= 2; // Update the products productsAdapter.Update(products); |
下面的編碼示範如何使用DB直接模式刪除一個產品,更新一個產品,然後添加一個新的產品:
C# |
1 2 3 4 5 6 7 8 9 10 11 12 |
NorthwindTableAdapters.ProductsTableAdapter productsAdapter = new NorthwindTableAdapters.ProductsTableAdapter(); // Delete the product with ProductID 3 productsAdapter.Delete(3); // Update Chai (ProductID of 1), setting the UnitsOnOrder to 15 productsAdapter.Update("Chai", 1, 1, "10 boxes x 20 bags", 18.0m, 39, 15, 10, false, 1); // Add a new product productsAdapter.Insert("New Product", 1, 1, "12 tins per carton", 14.95m, 15, 0, 10, false); |
建立自訂的插入,更新,刪除方法
用DB直接法產生的Insert(), Update(),和Delete()方法有時 候會感覺有點不方便,特別是當資料表有許多欄位的時候。看一下前面這個編碼例子,沒有IntelliSense的幫 助的話,不是很清楚Products表的哪個欄位對 應Update()和Insert()方法中的哪個輸入參數。有時候我們只要更新一到二個字 段或者需要一個自訂的Insert()方法,這個方法需要返回剛插入的記錄 的IDENTITY(自增)的欄位值。
要建立這樣的自訂方法,回到DataSet設計器。在TableAdapter上按右滑鼠,選擇“添加查詢”,然後回 到TableAdapter設定精靈。在第二屏上,我們可以指明要產生的查詢的類型。讓我們產生一個添加新 的product(產品)記錄,然後返回新添加記錄的ProductID值的方法。因此,選擇產生一個插 入(INSERT)型查詢。
圖25: 建立一個給Products表添加新記錄的方法
下一個屏顯示InsertCommand的CommandText屬性。在查詢語句後面,增添一 個SELECT SCOPE_IDENTITY()的查詢,這查詢將返回當前同一個操作範圍插入 入IDENTITY欄位的最後那個identity 值。(詳見技術文檔中關 於SCOPE_IDENTITY()的內容以及為什麼你應該使用SCOPE_IDENTITY()而不是 @@IDENTITY)。確認在添加SELECT語句前,你在INSERT語句後面添一個分號 。
圖26: 增添查詢返回SCOPE_IDENTITY()值
最後,把這個新方法命名為InsertProduct。
圖 27:放方法名字設成InsertProduct
當你返回DataSet設計器時,你將看到ProductsTableAdapter多了一個新的方 法,InsertProduct。如果對應Products表的每個欄位,這個新的方法沒有對應的參數的話,非常可能的原因是,你忘了給INSERT語句的結尾添加一個分號(semi-colon)。重新配 置InsertProduct方法,確認在INSERT和SELECT語句間有個分號。
在預設情形下,插入方法調用的是非查詢(non-query)方法,意即,他們只返回受影響的記錄數。但是,我們想要讓InsertProduct方法返回一個查詢返回的值,而不是受影響的記錄數。這可以把InsertProduct方法的ExecuteMode屬性改 成Scalar(標量)來實現。
圖 28:把ExecuteMode屬性改成Scalar
下面的編碼示範如何使用這個新的InsertProduct方法:
C# |
1 2 3 4 5 6 7 |
NorthwindTableAdapters.ProductsTableAdapter productsAdapter = new NorthwindTableAdapters.ProductsTableAdapter(); // Add a new product int new_productID = Convert.ToInt32(productsAdapter.InsertProduct("New Product", 1, 1, "12 tins per carton", 14.95m, 10, 0, 10, false)); // On second thought, delete the product productsAdapter.Delete(new_productID); |