關於Ado.Net Entity Framework 的理論、入門教學文章已不少了,但是很少有人講到在ASP.Net項目中實際項目應用的問題,往往學的時候輕鬆搞定,一上手項目就一頭霧水。
比如在教程中最常見的這種形式的使用方法:
using(MyObjectContext c=new MyObjectContext())
{
……
}
如果在實際應用中,每每需要串連資料庫,就造這麼一個代碼塊的話,那麼一個頁面訪問時就可能會建立數個資料庫連接,致使並發使用者訪問數大打折扣;
而假如只使用一個這樣的代碼塊的話,那麼由於分層、伺服器控制項、使用者控制項等因素,又難以將所有資料庫訪問操作都揉到這一個代碼塊當中;
那麼到底該怎樣做才是最佳方案呢?
這個問題或許是Entity Framework的使用者產生疑惑最多的一點。
我在此將結合自己的經驗,解答包括上述問題在內的一些在ASP.Net實際項目中容易產生的疑問。
準備工作
首先,我們需要搭建一個示範環境。
建立一個資料庫,並建立如下兩個表:
關係:Article的PostUser欄位對應到User的ID欄位
將兩個表分別填充一些資料:
產生Entity Framwork模型:
準備工作完成。
如何設計商務邏輯層?
如果要擴充實體類的功能,應該通過“部分類”(partial)實現:
如果需要藉助ObjectContext物件查詢或更新資料庫,應將ObjectContext定義為方法參數,而不是在商務邏輯層中建立ObjectContext對象。
例如,下面的方法不應該出現在商務邏輯層:
更好的做法是:
中高亮的重載方法只應在需要時才編寫,通常都可予以忽略。
(方法中的統計總數的代碼語句完全可以由LinQ語句替代完成,並且非常精簡,而這裡只是象徵性示範,別太在意)
如何快速通過主鍵擷取對應實體?
這樣是從緩衝中直接取出實體物件,效率非常高。
如何最佳化查詢效能?
可通過CompiledQuery.Compile()先行編譯查詢:
如何在同一頁面中共用一個ObjectContext?
一般來說,一個頁面只需要一個資料庫連接,這樣可以減少資料庫的並發壓力,使同一時間可以有更多使用者訪問網站。
而通常情況下,我們都使用ObjectContext的無參建構函式建立包含預設串連的ObjectContext對象,因此,在同一頁面中共用一個ObjectContext就能實現同一頁面共用一個資料庫連接的目標。
接下來我們將在頁面中放置兩個EntityDataSource控制項,分別擷取所有使用者及所有文章,並以ListView控制項顯示出來。
同時還要放置一個使用者控制項,用來擷取並顯示每個使用者曾發布的文章。
我們先來建立使用者控制項介面:
使用者控制項介面中僅包含一個ListView控制項。
(為了簡單起見,ul中的li代碼將由後台產生,然後直接綁定到這裡)
接著是後台代碼:
注意,這裡定義了一個ObjectContext屬性,程式將通過該屬性訪問資料庫及商務邏輯層,但該屬性並未在這裡初始化,而是要由使用此使用者控制項的頁面初始化該屬性。
接下來編寫頁面前台代碼:
簡單的放置並配置了兩個EntityDataSource及ListView,並放置了一個前面建立的使用者控制項。
後台代碼:
這裡也同樣設定了一個ObjectContext屬性,並在藍色高亮處重寫了OnInit,在其中進行初始化,並賦值給使用者控制項,然後在綠色高亮處重寫了Dispose,對ObjectContext進行釋放。
這樣使用者控制項就將和頁面使用同一個ObjectContext對象了。
然而,每個EntityDataSource還都會自己建立ObjectContext串連資料庫,這顯然不合我們的期望,解決辦法是分別註冊它們的ContextCreating、ContextDisposing事件,做如下處理:
這樣頁面雖然多次在不同的位置訪問資料庫,但僅使用一個ObjectContext、一個資料庫連接。
執行結果:
如何在多個ObjectContext共用一個資料庫連接?
EntityConnection即代表一個資料庫連接,可以通過建立EntityConnection對象,並將其分配給多個ObjectContext對象,實現多ObjectContext共用單串連,具體方法可參看MSDN:http://msdn.microsoft.com/zh-cn/library/bb738582.aspx
多ObjectContext共用一個串連,與整頁面共用一個ObjectContext有什麼不同呢?
一般來說感覺不到什麼不同,但當你將更改提交到資料庫時,單個ObjectContext將維護全部相關事務,一旦提交失敗將全部復原,而多個ObjectContext就可以分別處理各自的事務,相比之下更具靈活性。
結語
在這裡我僅以自己的經驗總結而出了一些問題和解決方案,若有其他疑問歡迎補充,共同探討。
針對上面的問題,如有更好的解決方案的話,也歡迎賜教。
下載範例原始碼:
下載本文的XPS版本: