在ASP.NET 2.0中操作資料之三十七:DataList批次更新_自學過程

來源:互聯網
上載者:User

導言

  在前面我們學習了如何建立item級的DataList。和可編輯的GridView一樣,每個DataList裡的item都包含一個Edit button,當點擊時,item會變的可編輯。item級的編輯在偶爾需要更新時沒什麼問題,但是在有些情況下使用者需要編輯大量的記錄。如果一個使用者需要編輯許多記錄,他會被迫去不停的去點擊Edit,作出修改,然後點擊Update,這些大量的點擊會妨礙他的工作效率。在這樣的情況下,一個好的選擇是提供一個完全可編輯的DataList,它的所有的item都處於編輯模式下,它的所有的值都可以通過點擊一個“Update All”button來更新。見圖1。


圖 1: 一個完全可編輯的DataList 的所有item都可以被修改

  本章我們來學習如何建立一個完全可編輯的DataList,它提供使用者更新supplier的address的功能。

第一步: 在DataList的 ItemTemplate建立一個可編輯的使用者介面

在前面建立一個標準的item級編輯的DataList時,我們使用了兩個template:

ItemTemplate — 包含唯讀使用者介面(使用 Label 顯示每個product的 name 和price).
EditItemTemplate — 包含編輯的使用者介面(兩個TextBox ).

  DataList的EditItemIndex屬性工作表明了哪個DataListItem使用EditItemTemplate來展示(如果有的話)。即ItemIndex的值等於DataList的EditItemIndex的DataListItem使用EditItemTemplate來展示。在一次只編輯一個item的情況下,這個模式工作的很好,但是在建立完全可編輯的DataList的時候就不適用了。

  對完全可編輯的DataList來說,我們需要所有的DataListItem都以可編輯的介面來展示。最簡單的方法是在ItemTemplate裡定義可編輯的介面。對修改supplier的address資訊而言,可編輯介面裡supplier表現為文本,address,city和country的值都用TextBox來表示。

  首先開啟BatchUpdate.aspx頁,添加一個DataList,將ID設為Suppliers。通過智能標籤添加一個名為SuppliersDataSource的ObjectDataSource控制項。


圖2: 建立一個名為SuppliersDataSource的ObjectDataSource

使用SuppliersBLL類的GetSuppliers()方法配置ObjectDataSource(見圖3)。象前面一章那樣,我們將直接使用 BLL而不是通過ObjectDataSource來更新supplier資訊。在UPDATE標籤裡選擇None(見圖4)。


圖 3: 使用GetSuppliers() 方法配置ObjectDataSource


圖 4: 設定UPDATE 標籤為None

  完成嚮導後,Visual Studio會自動產生DataList的ItemTemplate來在Label裡顯示每個資料欄位。我們需要修改這個template讓它提供編輯介面。ItemTemplate可以在設計器裡通過DataList的智能標籤上的Edit Templates或直接寫聲明文法來自訂。

  建立一個編輯介面,將supplier的name表現為文本,address,city和country表現為TextBox。完成這些後,你的聲明代碼應該和下面差不多:

<asp:DataList ID="Suppliers" runat="server" DataKeyField="SupplierID" DataSourceID="SuppliersDataSource"> <ItemTemplate>  <h4><asp:Label ID="CompanyNameLabel" runat="server"   Text='<%# Eval("CompanyName") %>' /></h4>  <table border="0">   <tr>    <td class="SupplierPropertyLabel">Address:</td>    <td class="SupplierPropertyValue">     <asp:TextBox ID="Address" runat="server"      Text='<%# Eval("Address") %>' />    </td>   </tr>   <tr>    <td class="SupplierPropertyLabel">City:</td>    <td class="SupplierPropertyValue">     <asp:TextBox ID="City" runat="server"      Text='<%# Eval("City") %>' />    </td>   </tr>   <tr>    <td class="SupplierPropertyLabel">Country:</td>    <td class="SupplierPropertyValue">     <asp:TextBox ID="Country" runat="server"      Text='<%# Eval("Country") %>' />    </td>   </tr>  </table>  <br /> </ItemTemplate></asp:DataList><asp:ObjectDataSource ID="SuppliersDataSource" runat="server" OldValuesParameterFormatString="original_{0}" SelectMethod="GetSuppliers" TypeName="SuppliersBLL"></asp:ObjectDataSource>

  注意:和前面一章一樣,需要為DataList開啟view state。

  在ItemTemplate裡我使用了兩個新的CSS類,SupplierPropertyLabel和SupplierPropertyValue。它們的風格設定和ProductsPropertyLabel和ProductPropertyValue CSS類一樣,並已經加入到Styles.css中。

.ProductPropertyLabel, .SupplierPropertyLabel{ font-weight: bold; text-align: right;}.ProductPropertyValue, .SupplierPropertyValue{ padding-right: 35px;}

完成這些後瀏覽頁面。如圖5所示,每個DataList的item用文本顯示supplier name,用TextBox顯示address,city和country。


圖 5:  DataList裡的每個Supplier都可編輯

第二步: 增加“Update All” Button

  圖5裡顯示的資訊暫時還沒提供Update按鈕。完全可編輯的DataList應該只包含一個"Update All"按鈕,而不是象前面那樣,每個item包含一個button。當點擊"Update All"時,DataList裡的所有記錄將被更新。本章我們將添加兩個"Update All"button- 一個在頁的上面,一個在下面(兩個都提供相同的功能)。

  先在DataList上面添加一個ID為UpdateAll1的Button。然後在DataList下面添加ID為UpdataAll2的Button。兩個Button的Text都設為"Update All"。最後為兩個Button的Click事件都建立一個event handler。我們建立一個方法,“UpdateAllSupplierAddress”,然後在事件處理中調用它。(而不是在兩個事件處理裡複製相同的代碼)

protected void UpdateAll1_Click(object sender, EventArgs e){ UpdateAllSupplierAddresses();}protected void UpdateAll2_Click(object sender, EventArgs e){ UpdateAllSupplierAddresses();}private void UpdateAllSupplierAddresses(){ // TODO: Write code to update _all_ of the supplier addresses in the DataList}

圖6是添加完"Update All"button後的頁面。


圖 6: 頁面添加了兩個“Update All” Button

第三步: 更新所有的Suppliers的 Address 資訊

  完成了將所有的item顯示為可編輯的介面和添加了“Update All”button後,剩下的事就是寫代碼執行批次更新。我們需要便利DataList的item,調用SuppliersBLL類的UpdateSupplierAddress方法。

  可以通過DataList的Items property 來訪問DataListItem集合。通過DataListItem的引用,我們可以從DataKeys集合裡擷取相關的SuppliserID,並引用ItemTemplate裡的TextBox,見下面的代碼:

private void UpdateAllSupplierAddresses(){ // Create an instance of the SuppliersBLL class SuppliersBLL suppliersAPI = new SuppliersBLL(); // Iterate through the DataList's items foreach (DataListItem item in Suppliers.Items) {  // Get the supplierID from the DataKeys collection  int supplierID = Convert.ToInt32(Suppliers.DataKeys[item.ItemIndex]);  // Read in the user-entered values  TextBox address = (TextBox)item.FindControl("Address");  TextBox city = (TextBox)item.FindControl("City");  TextBox country = (TextBox)item.FindControl("Country");  string addressValue = null, cityValue = null, countryValue = null;  if (address.Text.Trim().Length > 0)   addressValue = address.Text.Trim();  if (city.Text.Trim().Length > 0)    cityValue = city.Text.Trim();  if (country.Text.Trim().Length > 0)   countryValue = country.Text.Trim();  // Call the SuppliersBLL class's UpdateSupplierAddress method  suppliersAPI.UpdateSupplierAddress   (supplierID, addressValue, cityValue, countryValue); }}

  當使用者點擊一個"Update All"button時,每個Supplier DataList裡的DataListItem都執行UpdateAllSupplierAddress方法,並調用SuppliersBLL類的UpdateSupplierAddress方法,將相關的值傳過去。如果address,city或country裡不輸入值,UpdateSupplierAddress會接收一個空值(不是Null 字元串),而相關的欄位的結果會是一個database NULL。

  注意:你可以添加一個顯示的狀態Label,當批次更新完成後通過它來提供一些確認資訊。只更新 Addresses被修改過的記錄

  本章使用的批次更新法則為每個DataList裡的supplier調用UpdateSupplierAddress方法,無論address資訊是否被修改過。雖然這種盲目的更新一般情況下不會有什麼效能問題,但是如果你有做資料庫表的審計,那樣將會導致很多多餘的記錄。每次使用者點擊"Update All"button後,不管使用者是否有修改,系統裡都會為每個supplier產生一個一條新的審計記錄。

  ADO.NET的DateTable和DataAdapter類被設計用來支援批次更新那些僅僅被修改,刪除或新增的記錄。DataTable的每個row都有RowState property 來指明這個row是否是新增到DataTable或從它裡面刪除,修改,或沒有改變。當DataTable剛產生時,所有的row都被標記為未修改的,修改了row的任何列後row會被標記為已修改的。

  在SuppliersBLL類裡我們首先將supplier的記錄讀進SuppliersDataTable裡然後設定Address,City和Country列的值來更新指定的supplier的資訊,見以下代碼:

public bool UpdateSupplierAddress (int supplierID, string address, string city, string country){ Northwind.SuppliersDataTable suppliers =  Adapter.GetSupplierBySupplierID(supplierID); if (suppliers.Count == 0)  // no matching record found, return false  return false; else {  Northwind.SuppliersRow supplier = suppliers[0];  if (address == null)   supplier.SetAddressNull();  else   supplier.Address = address;  if (city == null)   supplier.SetCityNull();  else   supplier.City = city;  if (country == null)   supplier.SetCountryNull();  else   supplier.Country = country;  // Update the supplier Address-related information  int rowsAffected = Adapter.Update(supplier);  // Return true if precisely one row was updated,  // otherwise false  return rowsAffected == 1; }}

  無論值是否有被修改,這段代碼都將傳入的address,city和country的值賦給SuppliersDataTable的SuppliersRow。這個修改將使SuppliersRow的RowState屬性被標記為已修改的。當DAL的Update方法被調用時,它發現SupplierRow已經被修改了,因此向資料庫發送UPDATE命令。

  然而想象一下,我們為這個方法添加的代碼僅僅在和已經存在的值不一樣時才將傳入的address,city和country的值賦給SuppliersRow。在address,city和country沒有修改的情況下,SupplierRow的RowState仍然標記為未改變。這樣的結果是當DAL的Update方法被調用時,SuppliersRow沒有被修改,因此不會調用資料庫。使用以下的代碼代替前面盲目的賦值:

// Only assign the values to the SupplierRow's column values if they differif (address == null && !supplier.IsAddressNull()) supplier.SetAddressNull();else if ((address != null && supplier.IsAddressNull()) ||   (!supplier.IsAddressNull() &&   string.Compare(supplier.Address, address) != 0)) supplier.Address = address;if (city == null && !supplier.IsCityNull()) supplier.SetCityNull();else if ((city != null && supplier.IsCityNull()) ||   (!supplier.IsCityNull() && string.Compare(supplier.City, city) != 0)) supplier.City = city;if (country == null && !supplier.IsCountryNull()) supplier.SetCountryNull();else if ((country != null && supplier.IsCountryNull()) ||   (!supplier.IsCountryNull() &&   string.Compare(supplier.Country, country) != 0)) supplier.Country = country; 

增加了這些代碼後,DAL的Update方法僅僅在更改過address相關的值的那些記錄裡才向資料庫發送UPDATE命令。

  當然我們也可以追蹤傳入的欄位和資料庫資料是否有區別,如果沒有,就不需要調用DAL的Update方法。這種方法在你使用直接的資料庫命令時非常有效,因為直接的資料庫命令不會檢查SuppliersRow來決定是否需要調用資料庫。

  注意:每次UpdateSupplierAddress方法被調用時,都會調用一次資料庫來擷取需要更新的記錄的資訊。如果資料被修改,又要調用一次資料庫來更新資料。這個流程可以通過建立一個重載的UpdateSupplierAddress方法來最佳化,這個方法接受一個EmployeesDataTable ,它包含BatchUpdate.aspx頁的所有的修改。然後它會調用一次資料庫來擷取Suppliers表裡的所有記錄。在結果集裡僅僅是被修改過的記錄才能被更新。

總結

  本章學習了如何建立一個完全可編輯的DataList。通過它使用者可以快速的修改多個supplier的address資訊。我們首先定義了編輯介面 — address,city和country都以TextBox來表示 — 在DataList的ItemTemplate裡。然後我們在DataList的上下各添加了一個“Update All”button。使用者修改完後,點擊其中一個後,每個DataListItem都會調用SuppliersBLL類的UpdateSupplierAddress方法。

  祝編程愉快!

作者簡介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創始人,自1998年以來一直應用 微軟Web技術。大家可以點擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0資料教程》,希望對大家的學習ASP.NET有所協助。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.