2008-02-11 14:33 NameValueList
範例程式下載(VS 2008、VB.NET)
程式碼片段下載(NameValueList For VB.NET)
前言
之前曾經在文章中對CSLA.NET Framework做了些許的簡介,並列出了CSLA.NET的13種基本功,而本文的主要目的是針對基本功的「Name / Value List」的實作方法做說明。
雖然只是個簡單的範例,但是為了能讓讀者即早熟悉三層式程式開發架構,所以範例會以:資料存取層(Data Access Layer)、商業邏輯層(Business Logic Layer)、使用介面層(Presentation Layer)來做說明。
資料存取層會以LINQ(Language Integrated Query)來實作,所以本文也會對Microsoft的最新資料存取技術稍加說明。而商業邏輯層是以CSLA.NET Framework來實作,使用者介面層,如果可能會依續使用:Windows Form、ASP.NET、WPF來實作。
由於Visual Studio 2008已經正式上市,所以筆者決定往後的範例會以Visual Studio 2008來實作,而之前所發表的文章也會找時間全部改成Visual Studio 2008。雖然讀者目前可能尚無法取得繁體中文版的Visual Studio 2008,但是相信再過一兩個月就會有中文版的Visual Studio 2008 Express版提供下載。讀者若是想提早做練習,可以先下載英文版的來使用。
附加資料庫
下載的範例程式解壓縮後,在Data資料夾中會有BeautySalon.mdf及BeautySalon_log.ldf兩個檔案,讀者可將其附加到SQL Server中,因為程式範例是使用SQL Server 2005 Express,所以如果直接附加到SQL Server 2005 Express將不必更改專案中的連線字串。讀者若附加到別的SQL Server或想使用檔案系統資料庫,請在使用者介面專案的app.config(ASP.NET為web.config)修改如下所示區段的連線字串。
| <connectionStrings> <add name="DataAccess.My.MySettings.BeautySalonConnectionString" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=BeautySalon;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings> |
使用時機

如上圖所示,許多時候,當應用程式與使用者互動時,經常需要出現一個下拉選單,表列出一些選項提供使用者選擇,而顯示出來的文字是使用者容易看明白的文字。而當使用者選擇後會有一對應的鍵值(代碼),用以當依據再做進一步的查詢操作。也就是說,當有需要兩兩成對的資料組合列表時,用NameValueList這個商業物件就非常合適了。
新增空白方案
首先請開啟您的Visual Studio,接著在功能表上按「檔案(N)」à「新增(N)」à「專案(P)…」,由於我們希望是在一個方案下包含數個專案,所以請先在「專案類型」選擇「其它專案類型」、「Visual Studio 方案」、「空白方案」,並給於方案名稱及儲存位置。接著按【確定】


新增資料存取層專案
請在方案目錄樹下欲放置類別庫專案的方案資料夾上按滑鼠右鍵,並選擇「加入(D)」à「新增專案(N)…」,在加入新的專案的視窗中選擇您所熟悉的程式語言,並選擇「類別庫」範本,並給與專案名稱。


新增專案後,工具程式會幫您在專案下增加一個「Class.vb」檔案,因為沒有用到,所以請先將之刪除。接著新增用來當作資料存取的「LINQ to SQL類別」,請在類別專案節點上按右鍵,選擇「加入(D)」à「新增項目(W)…」,接著在新加入項目的視窗選擇「LINQ to SQL類別」範並給予一個名稱。



接著,會出現一個「物件關聯式設計工具」在左邊的頁面提供可將SQL資料庫的資料表拖曳到這個設計介面上,工具會自動建立資料類別。而右邊的頁面,可將資料庫的預存程序拖曳到這個設計介面上,工具會自動產生方法。
接下來會示範如何操作,以及稍加解譯一下工具所為我們產生的程式碼。請開啟「伺服器總管」,若在您的IDE工具中看不到「伺服器總管」,請在功能表上選擇「檢視(V)」à「伺服器總管(V)」,這樣「伺服器總管」就會出現在您的IDE工具中。

接著,要將前述附加的資料庫加入伺服器總管的資料連結,所以請在伺服器總管的資料連接節點上按滑鼠右鍵並選擇「加入資料連接(A)...」,在緊接著出現的視窗中加入範例資料庫的連結。


加入資料連結後,因為本次的範例只使用到「Products」這個資料表,所以請展開在伺服器總管中,範例資料庫的資料表,並在「Products」資料表上按滑鼠左鍵並拖曳到物件關聯式設計工具的設計介面上,此時工具會自動幫我們產生Products這個資料類別,及對應於資料表欄位的屬性。
至此,本範例的資料存取層的作業已經完成。讀者或許會很想知道,工具為我們產生了什麼程式碼,雖然在VS.NET功能強大的幫助下,許多操作只要「拉一拉」就能自動地產生許多程式碼,但是筆者建議稍微了解一下工具為我們所產生的程式碼會對於往後程式設計功力有所幫助,並且能在當工具無法產生【完全】符合自己理想功能時,有能力再對自動產生的程式碼追加功能。
所以如果您喜歡的話(但不是必須),請開啟方案總管,並「顯示所有檔案」並開啟「Products.desinger.vb」看看工具為我們產生了什麼程式碼。接著請按功能表的「建置(B)」à「建置方案(B)」,產生類別庫供接下來的資料邏輯層參考使用。

新增商業邏輯層專案
請依前述「新增資料存取層」相同步驟,新增一個類別庫專案,並刪除工具自動產生的「Class.vb」檔案。接下來為商業邏輯層專案加入參考,請在方案總管的商業邏輯層專案節點按滑鼠右鍵並選擇「加入參考(R)...」。


因為筆者一系列教學的商業邏輯層是使用CSLA.NET Framework來實作,所以請將依前述「CSLA.NET Framework簡介」文章所介紹的方法所建置的Csla.dll類別庫加入參考。並匯入「Csla」與「Csla.Data」命名空間。
而在商業邏輯層中會使用到前述「資料存取層專案」所建立的類別庫,所以請再將該類別庫加入參考。

因為資料存取的操作是使用微軟最新資料庫存取技術的LINQ,所以必須將System.Data.Linq也加入參考。而對資料庫連線字串一般是會由app.config(web.config)中取得,而對app.config內容的存取必須將System.configuration加入參考。

加入商業物件
接下來真正進入實作NameValueList程式碼實作的部分,請在方案總管中專案的節點上按滑鼠右鍵並選擇「加入(D)」à「類別(C)...」並給定類別名稱,為專案加入類別。

接著請參閱下列的程式碼,請先別急著將這些程式碼鍵入,因為CSLA.NET Framework另一個令人著迷的地方是,它將必要的程式碼整理得非常有規則,那些功能的程式碼該放在那裏,都有規定,雖然不必完全參照,但是如果遵循的話,將來後續程式的維護將比較容易,且團隊中也容易溝通。最重要的是有一定的準則就可以用插入程式碼片段的方式減少Coding的時間,將來更可以使用程式產生器來產生必要的程式碼。
請在看完底下的程式解說後,了解各段程式碼所代表的意義後, 再使用插入程式碼片段的方式為自己建立所需的程式碼。(插入程式碼片段會在另外的文章中介紹)
#Region " 工廠方法 " Private Shared mList As ProductList Public Shared Function GetList() As ProductList If mList Is Nothing Then End Function ''' <summary> Public Shared Sub InvalidateCache() mList = Nothing End Sub Private Sub New() #End Region #Region " 資料存取 " Private Overloads Sub DataPortal_Fetch() #End Region End Class
|
程式碼說明
|
首先,將新加入的的類別繼承Csla.NameValueListBase這個基礎類別,而(Of Guid, String)是使用泛型的技巧,先前有提過NameValueList是在有需要兩兩成對的資料組合列表時使用,第一個參數是代表這組資料第一個資料的資料型別(本例是Guid),而第二個參數是代表這組資料第二個資料的資料型別(本例是String),讀者可視實際資料庫所規畫使用適當的型別。
Private Shared mList As ProductList Public Shared Function GetList() As ProductList If mList Is Nothing Then End Function |
由於類似這種讀取兩兩成對的資料組合列表,相同的組合在使用者介面的專案中可能會出現在許多場合,比如在輸入進貨單時有需要做【貨品選擇】,而在出貨單、庫存盤點‥‥等也都需要做 【貨品選擇】,而貨品的資料一般是不會變動得很頻繁,不必在每次有需求時都進資料庫讀取一次,因此可宣告一個變數:Private Shared mList As ProductList,當有資料需求時首先會檢查該變數是否為Nothing:If mList Is Nothing Then,若為Nothing表示是第一次需求資料,所以必需由資料庫中讀取:mList = DataPortal.Fetch(Of ProductList)(),否則就直接將在記憶中的資料傳回即可。
Public Shared Function GetList() As ProductList,是為類別宣告一個方法,將來在使用者介面專案中可使用本方法來取得資料物件。
Public Shared Sub InvalidateCache() mList = Nothing End Sub |
為類別宣告一個方法:Public Shared Sub InvalidateCache(),功用是當如果別的商業物件,或一些外部的操作造成資料庫的內容己經有修改,那就可使用本方法來清空在記憶體中的快取。
| Private Overloads Sub DataPortal_Fetch() Me.RaiseListChangedEvents = False Using ctx = ContextManager(Of DataAccess.ProductsDataContext).GetManager(Database.BeautySalonConnection) IsReadOnly = False Dim data = From p In ctx.DataContext.Products Select p.Id, p.Name For Each row In data Me.Add(New NameValuePair(row.Id, row.Name)) Next IsReadOnly = True End Using Me.RaiseListChangedEvents = True End Sub |
最後就是,利用LINQ技術將在資料庫中的資料讀入到物件中。讀者應該還記得在之前的「資料存取層專案」中的操作,若有照建議參看一下工具為我們產生的程式碼,應該會發現工具為我們產生了一個繼承自:System.Data.Linq.DataContext的類別(本例是:ProductsDataContext),也為我們自動產生了數個建構函式(Public Sub New(.......)),這些建構函式主要是用來告訴程式如何與資料庫建立連線,因此我們可利用如下的方式:
| Using ctx = ContextManager(Of pDataContex).GetManager("連線字串") |
也就是傳入一個在資料存取層中所建立的DataContext類別,和連線字串,即可取得Linq物件(ctx),可做為接下來對資料庫的操作。而在本範例中連線字串的取得,使用了另一技巧,該技巧會在另一篇文章中詳細說明,在這裏讀者只要理解是傳入一個與資料庫連線及驗証有關的字串即可。
| Dim data = From p In ctx.DataContext.Products Select p.Id, p.Name For Each row In data Me.Add(New NameValuePair(row.Id, row.Name)) Next |
接著是使用LINQ語法向資料庫中讀取資料:From p In ctx.DataContext.Products Select p.Id, p.Name,這句指令的意思由資料表Products讀取出Id與Name兩個欄位,相當於SQL指令的「SELECT Id, Name FROM Products」,而LINQ語法會在另一系列教學文章中作說明。資料由資料庫中讀出後,接著就是將資料加入物件中。
至此,整個NameValueList的講解已經完了,聰明的讀者是否會發現,整段實作NameValueList類別的程式碼,往後要依情況再製作別的NameValueList類別,其實有許多程式碼是不變的,變的大概只是一些識別子(Identifier)名稱,所以可以整理成程式碼片段,將來就直接插入使用就可以了。程式碼片段的使用會在另篇文章中說明,底下會將本範例中實作NameValueList類別的程式碼再列出,並將需要更動的部分作上記號:
#Region " 工廠方法 " Private Shared mList As ProductList Public Shared Function GetList() As ProductList If mList Is Nothing Then End Function ''' <summary> Public Shared Sub InvalidateCache() mList = Nothing End Sub Private Sub New() #End Region #Region " 資料存取 " Private Overloads Sub DataPortal_Fetch() #End Region End Class |
使用介面層
為了不造成篇幅內容重複,所以接下來在使用介面的實作方面,請參考其它發表的文章,Windows Form用例可參考:「資料繫結」。
結語
本篇文章除了介紹CSLA.NET基本功的NameValueList的實作方法外,也順便詳細介紹使用Visual Studio開發三層式架構應用程式的方法,和Microsoft最新資料存取技術LINQ。運用了多張圖文,期望讓讀者也能熟習Visual Studio開發工具的使用。而往後其它基本功的介紹,為降低文章篇幅及減少筆者工作量,將直接進入程式碼解說部分,所以請讀者在學習NameValueList實作的同時,也能熟練Visual Studio開發工具的使用。
我要評分:





