在ASP.NET 2.0中操作資料之六十八:為DataTable添加額外的列_自學過程

來源:互聯網
上載者:User

導言:

  當向類型化的資料集(Typed DataSet)添加一個TableAdapter時,相應的DataTable的構架已經由TableAdapter的主查詢定義好了.比如,如果主查詢返回A, B,C這3個域,那麼 DataTable將有對應的3個列A, B,和C.除了主查詢以外,TableAdapter還可以包含其他的查詢,可能是返回基於某些參數的資料。比如,ProductsTableAdapter的主查詢返回所有產品的資訊,此外,ProductsTableAdapter還包含諸如GetProductsByCategoryID(categoryID) 和 GetProductByProductID(productID)的方法,它們根據指派的參數返回特定的產品資訊.

  如果TableAdapter的方法返回的列涵蓋在主查詢裡,工作起來沒有問題。但如果返回的列並沒有涵蓋在主查詢,那麼我們就需要對DataTable的構架進行擴充.在第35章《使用Repeater和DataList單頁面實現主/從報表》裡,我們向CategoriesTableAdapter添加方法以返回 CategoryID, CategoryName, Description和NumberOfProducts列。其中前3列是涵蓋在主查詢裡的,而NumberOfProducts列沒有在主查詢裡定義,它返回的是每個category相關產品的數目.我們可以向CategoriesDataTable手工添加一列,以便於統計從新方法返回的NumberOfProducts列的值.

  在第52章《使用FileUpload上傳檔案》我們探討過,對使用ad-hoc SQL statements構建且其方法返回的列超出主查詢範圍的TableAdapters必須多加留意.因為一旦重新回合設定嚮導的話,它將對TableAdapter的方法進行更新,使其返回的列與主查詢相匹配.不過如果使用預存程序的話就不會出現這種情況.

  在本文我們將考察如何擴充DataTable的構架以包含額外的列。我們都知道使用ad-hoc SQL statements構架的TableAdapter不穩定,本文我們將用預存程序來構架.你可以參考第65章《在TableAdapters中建立新的預存程序》和第66章《在TableAdapters中使用現有的預存程序》來擷取設定TableAdapter使用預存程序的更多資訊.

第一步:向ProductsDataTable添加一個PriceQuartile列

  在第67章裡我們建立了一個名為NorthwindWithSprocs的類型化的資料集.該資料集目前包含2個DataTables:ProductsDataTable以及 EmployeesDataTable。其中ProductsTableAdapter包含3個方法:

.GetProducts——主查詢,返回Products表的所有記錄
.GetProductsByCategoryID(categoryID)——根據指定的categoryID值返回所有產品
.GetProductByProductID(productID)——根據指定的productID值返回所有的產品

  主查詢及另外2個方法都返回相同的資料列,也就是Products表的所有列,並沒有返回Categories 以及Suppliers表的相關資料.

  在本文,我們將向ProductsTableAdapter添加一個名為GetProductsWithPriceQuartile 的方法,它返回所有的產品.除了標準的資料列外,它還返回PriceQuartile列,它用四分位元來衡量產品價格下跌程度.如果產品價格上升了25%,那麼其值為1,如果下降為25%,那麼其值為4.在我們建立一個預存程序來返回這種資訊之前,我們首先需要更新ProductsDataTable,新添一列來包含GetProductsWithPriceQuartile方法返回的 PriceQuartile值.

  開啟NorthwindWithSprocs資料集,在ProductsDataTable上按右鍵,選擇“ Add” ,再選擇“Column”.


圖1:向ProductsDataTable新添一列

  這將向DataTable新添一列,名為“Column1”,類型為System.String.我們需要將該列的名稱改為“PriceQuartile”,類型改為System.Int32,因為它的值介於1到4之間.在ProductsDataTable 選中我們新添加的列,在屬性視窗裡設定其Name屬性為 “PriceQuartile”,DataType屬性為System.Int32.


圖2:設定該新列的Name 和 DataType屬性

  就像圖2所示,我們還可以設定其它的屬性.比如,是否該列的值必須為unique;如果該列為自增列,其值是否允許為NULL等等.不過我們這裡使用其預設值.

第二步:建立GetProductsWithPriceQuartile方法

  現在我們已經對ProductsDataTable進行了更新以包含PriceQuartile列,我們將要建立一個GetProductsWithPriceQuartile方法.在TableAdapter上單擊右鍵,再選擇“Add Query”.這將開啟TableAdapter查詢設定嚮導,它首先詢問我們是使用ad-hoc SQL statements還是使用現有的預存程序或建立一個預存程序.我們選擇“Create new stored procedure”,再點Next.


圖3:在TableAdapter嚮導裡建立新的預存程序

  接下來,如圖4所示,嚮導詢問我們添加的是那種類型的查詢,由於GetProductsWithPriceQuartile方法將返回Products表的所有記錄以及所有列,我們選擇“SELECT which returns rows”項,再點Next.


圖4:查詢將是一個返回多個行的SELECT Statement

接下來,我們在嚮導裡鍵入如下的查詢:

SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued, NTILE(4) OVER (ORDER BY UnitPrice DESC) as PriceQuartileFROM Products

  上述查詢使用了SQL Server 2005新增的NTILE function函數,它將結果劃分為4組,將UnitPrice值按降序分組.

  不幸的是,查詢構造器(Query Builder)不能解析關鍵字OVER,並拋出一個錯誤資訊。因此,直接在嚮導的文字框裡鍵入上述代碼,而不要使用查詢構造器.

  注意:關於NTILE以及SQL Server 2005的其它函數的更多資訊,你可參閱文章《Returning Ranked Results with Microsoft SQL Server 2005》(http://www.4guysfromrolla.com/webtech/010406-1.shtml)以及SQL Server 2005 Books Online的《Ranking Functions section》部分(http://msdn2.microsoft.com/en-us/library/ms189798.aspx)

  完成後,點Next, 嚮導將要我們為新預存程序重新命名,我們取名為Products_SelectWithPriceQuartile再點Next.


圖5:將新預存程序命名為Products_SelectWithPriceQuartile

  最後我們要為TableAdapter的方法命名,選中“Fill a DataTable” 和 “Return a DataTable”兩項,並重新命名為 FillWithPriceQuartile 和GetProductsWithPriceQuartile.


圖6:對TableAdapter的方法命名並點Finish

  當指定了SELECT查詢,並對預存程序和TableAdapter的方法命名後,點Finish完成嚮導。這時你將看到1到2條警告資訊,說“The OVER SQL construct or statement is not supported.” 不必理會它.

  完成嚮導後,該TableAdapter將會包含FillWithPriceQuartile 和GetProductsWithPriceQuartile方法,並且資料庫將包含一個名為Products_SelectWithPriceQuartile的預存程序。花點時間來驗證一下,檢查資料庫,如果你沒有看到我們剛添加的預存程序,在預存程序檔案夾上按右鍵,選“重新整理”.


圖7:驗證新方法是否添加到TableAdapter


圖8:確保資料庫包含Products_SelectWithPriceQuartile預存程序

  注意:使用預存程序來替換ad-hoc SQL statements的好處之一是重新運行TableAdapter設定嚮導的話並不會改動預存程序返回的列.我們可以作一個驗證,在TableAdapter上按右鍵,選“Configure”項,以啟動嚮導,然後點Finish完成嚮導。接下來,我們在資料庫裡查看Products_SelectWithPriceQuartile預存程序.我們注意到其返回的列並沒有發生變化.如果我們使用的是ad-hoc SQL statements的話,重新運行嚮導將會使查詢返回的列與主查詢的列相匹配,因此它將把GetProductsWithPriceQuartile方法裡使用的查詢裡的NTILE statement刪除掉.

  當調用資料訪問層的GetProductsWithPriceQuartile方法時,TableAdapter將執Products_SelectWithPriceQuartile預存程序,並為返回的每條記錄向ProductsDataTable添加對應的row.預存程序返回的資料域(data fields)將映射到ProductsDataTable的列.因為該預存程序要返回一個PriceQuartile資料域,所以它的值將分配給ProductsDataTable的PriceQuartile列.

  對於那些不返回PriceQuartile資料域的方法而言,PriceQuartile列的值由其DefaultValue屬性指定. 如圖2所示,該預設值為DBNull。如果你想指定為其他值,僅僅改動DefaultValue屬性即可,但一定要是一個有效值(比如,PriceQuartile列的值一定要是一個System.Int32類型的值).

  現在我們完成了向DataTable添加額外列的必要的步驟,接下來我們要建立一個ASP.NET 頁面來展示每個產品的 name, price,以及price quartile.不過我們要先對商務邏輯層進行更新,以包含一個方法來調用資料訪問層的GetProductsWithPriceQuartile方法.我們將在第3步更新商務邏輯層,在第4步建立一個ASP.NET頁面.

第三步:更新商務邏輯層

  我們在表現層調用新添加的GetProductsWithPriceQuartile方法以前,必須在商務邏輯層添加相應的方法,開啟ProductsBLLWithSprocs class類檔案,添加如下的代碼:

[System.ComponentModel.DataObjectMethodAttribute (System.ComponentModel.DataObjectMethodType.Select, false)]public NorthwindWithSprocs.ProductsDataTable GetProductsWithPriceQuartile(){ return Adapter.GetProductsWithPriceQuartile();}

  就像其它方法一樣,GetProductsWithPriceQuartile僅僅調用資料訪問層對應的GetProductsWithPriceQuartile方法並返回其結果.

第四步:在一個ASP.NET頁面展示Price Quartile資訊

  完成對商務邏輯層的修改後,我們將建立一個ASP.NET頁面來顯示每個產品的price quartile資訊.開啟AdvancedDAL檔案夾裡的AddingColumns.aspx頁面,從工具箱拖一個 GridView控制項到頁面,設定其ID為Products.在其智能標籤裡將其綁定到一個名為ProductsDataSource的新的ObjectDataSource控制項,設定該控制項調用ProductsBLLWithSprocs class類的GetProductsWithPriceQuartile方法,在UPDATE, INSERT,和DELETE標籤裡選“(None)”.


圖9:設定ObjectDataSource調用ProductsBLLWithSprocs類


圖10:調用GetProductsWithPriceQuartile方法擷取產品資訊

  完成設定嚮導後, Visual Studio會為GridView添加BoundField或CheckBoxField列,其中包括PriceQuartile列. 將ProductName, UnitPrice,PriceQuartile以外的列全部刪除,設定UnitPrice列為貨幣格式.並將UnitPrice 和 PriceQuartile列放在右邊,置中。 最後分別將這3列的HeaderText屬性設定為“Product”, “Price”,“Price Quartile”。同時啟用GridView控制項的排序功能.

  作上述修改後, GridView 和 ObjectDataSource控制項的聲明代碼看起來和下面的差不多:

<asp:GridView ID="Products" runat="server" AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="ProductsDataSource"> <Columns> <asp:BoundField DataField="ProductName" HeaderText="Product"  SortExpression="ProductName" /> <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"  HeaderText="Price" HtmlEncode="False"  SortExpression="UnitPrice">  <ItemStyle HorizontalAlign="Right" /> </asp:BoundField> <asp:BoundField DataField="PriceQuartile" HeaderText="Price Quartile"  SortExpression="PriceQuartile">  <ItemStyle HorizontalAlign="Center" /> </asp:BoundField> </Columns></asp:GridView><asp:ObjectDataSource ID="ProductsDataSource" runat="server" OldValuesParameterFormatString="original_{0}" SelectMethod="GetProductsWithPriceQuartile" TypeName="ProductsBLLWithSprocs"></asp:ObjectDataSource>

  如圖11為在瀏覽器裡登入該頁面的情況,我們注意到,最開始產品按price的降序排列,同時每個產品都有相應的PriceQuartile值,當然這些資料也可以按其它標準來排序,如圖12所示。


圖11:產品按Prices來排序


圖12:產品按名稱來排序.

  注意:只需要很少的代碼,我們就可以根據每行PriceQuartile值的不同而顯示不同的顏色,比如對值為1的行顯示為淺綠色,對值為2的行顯示為淺黃色,以此類推.你可以花點時間來實現該功能,如果有必要的話,你可以參閱第11章《基於資料的自訂格式化》

另一種途徑——建立另一個TableAdapter

  正如我們在本文看到的,當向TableAdapter添加的方法返回的列超出了主查詢範圍的時候,我們可以向DataTable添加相應的列即可.對TableAdapter而言,如果當其包含的返回“額外列”的方法較少且“額外列”不是很多的時候,這種途徑才能正常工作。

  除了往DataTable添加列以外,我們還可以對DataSet添加另外的TableAdapter,其包含的方法就是那些需要返回“額外列”的方法.就本問而言,我們可以向DataSet添加另一個名為ProductsWithPriceQuartileTableAdapter的TableAdapter,它將Products_SelectWithPriceQuartile預存程序作為它的主查詢,對要擷取price quartile資訊的ASP.NET頁面來說,只需調用 ProductsWithPriceQuartileTableAdapter即可;而不需要擷取price quartile資訊的頁面只需要調用ProductsTableAdapter即可.

  這種另外新添加的TableAdapters可能導致某些功(functionality)、作業(task)重複.比如,如果那些展示PriceQuartile列的頁面也要啟用insert, update,delete功能的話,那麼就要對ProductsWithPriceQuartileTableAdapter的InsertCommand, UpdateCommand,DeleteCommand屬性進行適當的設定.而我們已經對ProductsTableAdapter的這3個屬性進行過設定了,這時就有2種方法來對資料庫裡的產品進行添加、更新、刪除操作了——使用ProductsTableAdapter類或 ProductsWithPriceQuartileTableAdapter類.

  本文供下載的代碼裡,在NorthwindWithSprocs資料集裡包含了ProductsWithPriceQuartileTableAdapter class類,示範了這2種方法.

總結:

  在大多數情況下,TableAdapter的所有方法返回的資料列都是相同的,但有極少數方法會返回主查詢沒有包含的“額外列”.比如我們在第35章《使用Repeater和DataList單頁面實現主/從報表》裡,我們向CategoriesTableAdapter添加了一個方法,該方法除了返回主查詢裡的列外,還返回了一個NumberOfProducts列.而在本文,我們考察類了向 ProductsTableAdapter 添加一個方法以返回一個沒有包含在主查詢裡的PriceQuartile列.對這種返回來的“額外列”,我們需要向DataTable添加一個對應的列.

  如果你打算手工向DataTable添加列,我們建議一使用預存程序.如果用ad-hoc SQL statements的話,任何時候只要重新運行TableAdapter設定嚮導,使用者所做的所有定製都要被覆蓋.而用預存程序的話就不會出現這種情況.

  祝編程快樂!

作者簡介

  本系列教程作者 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.