2011年8月25日 星期四

Asp.net中MVC2以linq把資料庫的內容連結下拉式清單 (VB.net版本)

原由:
我係一間醫院從事技術支援,剛好醫院要求我寫一個web版 Inventory system (電腦器材管理系統),由於我部門只有我懂寫網頁,並且醫院資源有限,但我從前只會寫VB...所以我便決定以asp.net 加vb.net來寫。

新版的asp.net加了MVC2作為基礎. 記得我所接觸過的mvc是Java的struts,由於mvc的架構是在controller中編寫程序碼來連結資料庫,並與在Views 的部份編寫用戶介面 (Graphical user interface),其架構十分簡潔地分開了前台和後台兩層,故此個人認為此種架構的好處是一方面可以幫助其他編程人員(programmer)容易了解程式原作者的程序碼,另一方面促使編程人員與介面設計人員之間容易分工,畢竟有些人會專長於設計用戶介面(GUI),而另一些人則會擅於編寫連結資料庫的程序碼。
我曾在網上去找相關的教學文章,但發覺以教用vb.net來寫asp.net MVC2 的資料實存在很少。相反,以C#來寫asp.net mvc2則很多,經過我鑽研了幾星期,終於寫完了程式的主要部份,並且貼下一些程序碼及步驟是關於 [Asp.net中MVC2以linq把資料庫的內容連結下拉式清單] 給大家參考!!
本文重點在於編寫VB.net程序碼以linq把資料庫的資料連結下拉式清單以顯示出用戶介面所以我只列出重點:
基本的vb.net來寫asp.net MVC2 請參考以下官方:
http://www.asp.net/mvc/tutorials/create-a-movie-database-application-in-15-minutes-with-asp-net-mvc-vb
------------------------------------------------------------------------


我用的發展平台包括了Microsoft Visual Web Developer 2008 Express Edition, .NET framework 3.5 sp1, Microsoft SQL Server 2008 Express Edition.
我的project 名稱叫Inventroy Control,主要編寫的檔案是Controllers 內的 HomeController.vb和Views->Home->Edit.aspx,結構如下圖示:


先說HomeController.vb內的程序碼是關於資料庫的連結,利用LINQ來獲取資料庫的資料以提供Edit.aspx,而Edit.aspx內的程序碼就是把資料用下拉式清單顯示在用戶介面。
好了,先看controller部份,在HomeController.vb內,編寫的程序碼如下:


   1:  Function Edit() As ActionResult
   2:          Dim viewModel = (From m In _stock.ITStock Order By m.SerialNum Ascending _
   3:                               Where m.SerialNum = "id123" _
   4:                               Select m).First()
   5:          ViewData("VendorName") = GetVendorItems()
   6:          Return View(viewModel)
   7:  End Function
   8:   
   9:   
  10:  Private Function GetVendorItems() As List(Of SelectListItem)
  11:          Dim IQuery As IQueryable(Of SelectListItem)
  12:          Dim VendorList As New List(Of SelectListItem)
  13:          IQuery = (From p In _stock.Vendor _
  14:              Select New SelectListItem With {.Text = p.CompanyName, .Value = p.VendorID})
  15:          'VendorList.Add(New SelectListItem With {.Text = "Not defined", .Value = 0})
  16:          VendorList.AddRange(IQuery.ToList)
  17:          Return VendorList
  18:  End Function

以上Edit函式內的程序碼就是關於資料庫的連結,利用LINQ來獲取資料庫的資料以提供Edit.aspx,為了程序整潔,我寫了名為GetVendorItems的函式(function),此函式會在Edit函式內被呼召並傳回了 SelectListItem所堆積的list。而GetVendorItems所傳回的List就是用來給Edit函式,以提供Edit.aspx作下拉式清單的多筆項目,而GetVendorItems內先要宣告的變數包括了名為Iquery,其(data Type)資料種類是SelectListItem所堆積的IQueryable,另一個宣告的變數名為VendorList,其(data Type)資料種類則是SelectListItem所堆積的list。而這兩個變數是用來儲存LINQ查詢的結果,並傳回的Edit函式。

   1:  IQuery = (From p In _stock.Vendor _
   2:              Select New SelectListItem With {.Text = p.CompanyName, .Value = p.VendorID})

再來,以上的一句就是以Linq查詢資料,先說 _stock是什麼意思,_stock 其實是一個資料庫的物件,由我用Visual web developer 以Linq的精靈產生出來,詳細請參考上面所提及的用vb.net來寫asp.net MVC2 基本中Linq連接部份。簡單來說,_stock已包含了多張資料表,其中一個是Vendor 的資料表,以上這句表示用linq查訊名為 _stock.Vendor 的物件(即查詢Vendor 的資料表),再把查訊結果儲存到p中,然後新增SelectListItem,並把先前p內所儲存的vendor 資料表中的companyName和VendorID分別儲存於SelectListItem的Text和value。(若您懂得HTML,您會知道html中編寫下拉式清單是以option Tag表示,而option tag 同樣包括了Text和value,如下)

而SelectListItem的Text和value,在往後編寫Edit.aspx時,是會被用作下拉式清單中的每筆option內的value值。
okay,以上執行完所傳回的結果是多個SelectListItem,並用了先前所宣告的變數Iquery儲存。當Iquery有了所有SelectListItem的值後,下一步便是將之轉變成函式GetVendorItems所要傳回的資料種類(即SelectListItem所堆積的list)。而轉變方式便是下面的程序碼。


   1:  VendorList.AddRange(IQuery.ToList) 

以上這句是把先前宣告的變數VendorList用來作儲存Iquery中的結果。而Iquery必須利用toList 方法去轉成list才能被VendorList儲存。不然,變數VendorList與變數Iquery的資料種類不同會引起程序上錯誤。在最後 Return VendorList執行後便傳回GetVendorItems的結果。
說回Edit函式,ViewData("VendorName") = GetVendorItems() 是指把GetVendorItems傳回的結果存到ViewData("VendorName") 這個標籤中,之後可以編寫在Edit.aspx時,透過ViewData("VendorName")這個標籤來顯示結果到用戶介面。
好了,現在可以看看Views->Home->Edit.aspx內,編寫的程序碼如下:


以上程序碼便是把結果用下拉式清單顯示到用戶介面。Html.DropDownListFor 是建立下拉式清單,其首個參數是關係到先前在HomeController.vb的Edit函式內兩句沒提及的程序碼,分別是

   1:  Dim viewModel = (From m In _stock.ITStock Order By m.SerialNum Ascending _
   2:                               Where m.SerialNum = "id123" _
   3:                               Select m).First()
   4:            Return View(viewModel) 

以上首句是用linq查訊 _stock.ITStock 的物件(即查詢_stock內另一個資料表叫ITStock),再把查訊結果存到m中,但是查訊結果是m內ITStock 資料表中的欄位SerialNum 必須等於 "id123"。由於在資料庫設計中,一件貨物(STOCK)只會有一個(unique)唯一的 serial number,並且是設為primarykey,故此我們便用.First()傳回一筆記錄,然後將結果存到viewModel 這個標籤中,之後Return View(viewModel) 會把結果傳到Edit.aspx,這樣可以在編寫Edit.aspx時,呼叫model物件中所儲存的一筆stock資料來顯示到用戶介面。而此一筆stock資料在資料庫設計中包含幾個欄位,例如stock name, stock type, stock price 等,並因與最先提及_stock.Vendor 物件中的vendor資料表有一對多的關系,(即一個vendor可以有多件stock)。故此,此一筆stock資料會有個欄位叫vendor id 作為foreign key以連接vendor資料表中的primary key。
 
以上明白後,說回 Html.DropDownListFor首個參數,就是要把model物件中的ITStock資料表內的欄位vendor id拿出來對應相同的option選項,舉例來說,當有五間公司就會有五個OPTION選項,而model物件中的ITStock資料表內的欄位vendor id便是用來決定五項中哪一項被選(selected),即在對應的option會selected (若您懂得HTML您會知道html中option下拉式清單的selected 如下)


而Html.DropDownListFor 內的第二參數是用vb語法中的CType把先前ViewData("VendorName") 這個標籤中SelectListItem所堆積的list轉變成可列出list種類,以顯示到用戶介面 。舉例來說,當有五間公司,ViewData("VendorName") 這個標籤中SelectListItem所堆積的list就會有五個SelectListItem以提供五個OPTION選項。
而用戶介面 最後結果,如下圖:

補充:
先前在HomeController.vb中GetVendorItems的函式內,有綠色的一句程序碼是comment 不會執行,如下:


   1:  'VendorList.Add(New SelectListItem With {.Text = "Not defined", .Value = 0}) 

此句程序碼是用於個別的情況,例如您想在下拉式清單新增一項 ---請選擇--- 的選項,但不想在資料庫中儲存---請選擇--- ,便可以用此句程序碼新增 ---請選擇--- 的選項(即HARD CODE)。

而其實對於一些高手來說,以上asp.net程序碼所有的寫法其實可以簡化,我有說錯大家請多多包涵 :p

下面我再重新貼上完整的程序碼方便學習:
HomeController.vb:

   1:  Function Edit() As ActionResult
   2:          Dim viewModel = (From m In _stock.ITStock Order By m.SerialNum Ascending _
   3:                               Where m.SerialNum = "id123" _
   4:                               Select m).First()
   5:          ViewData("VendorName") = GetVendorItems()
   6:          Return View(viewModel)
   7:  End Function
   8:   
   9:   
  10:   
  11:  Private Function GetVendorItems() As List(Of SelectListItem)
  12:          Dim IQuery As IQueryable(Of SelectListItem)
  13:          Dim VendorList As New List(Of SelectListItem)
  14:          IQuery = (From p In _stock.Vendor _
  15:              Select New SelectListItem With {.Text = p.CompanyName, .Value = p.VendorID})
  16:          'VendorList.Add(New SelectListItem With {.Text = "Not defined", .Value = 0})
  17:          VendorList.AddRange(IQuery.ToList)
  18:          Return VendorList
  19:  End Function
  20:   


Edit.aspx的程序碼:

沒有留言:

張貼留言