Entity Framework 4.1/4.3 之四(DBContext 之 1 DBContext 是誰)
倫敦奧運如火如荼的開幕了,人們還是願意拿來和北京奧運小比一下,大多仁者見仁,智者見智。說的都還有理。在此預祝倫敦奧運圓滿結束,畢竟我是007的忠實Fans。
大家還記得Entity Framework 4.1/4.3 之一(概念篇)中我介紹過ObjectContext ObjectSet 以及 DBContext 和DBSet的定義。在使用了4.0很長一段時間后,我向4.3進行了過渡,這個過渡的過程中,我認識並使用了 DBContext 和 DBSet 。感覺很不錯。下面我通會表格來分別展示一下ObjectContext ObjectSet DBContext DBSet:
DbContext |
Relevant EF4 feature/class (有關EF4中的功能/類) |
General purpose(共同的作用) | Benefit of DbContext API (DBContext API 的優勢) |
DbContext | ObjectContext | Represent a session with the database. Provide (與數據庫進行會話) |
Exposes and simplifies most (簡化ObjectContext中的常用功能) |
DbSet | ObjectSet | Provide set operations for entity types, such as Add, (提貨對數據實體的操作,如增、改、查,繼承了DBQuery的一些功能) |
Exposes and simplifies most (簡化ObjectSet中的常用功能) |
DbQuery | ObjectQuery | Provide querying capabilities (提供查詢功能) |
The query functionality of () |
Change Tracker API |
ObjectContext. ObjectStateManager |
Get access to change tracking information and operations (獲取發生的跟蹤信息和操作(例如,原始值,當前值)並進行管理。) |
Simpler and more intuitive API (簡化更多API使用) |
Validation API | n/a | Provide automatic validation of data at the data (提供自動化的數據驗證,驗證功能在.Net4已經存在) |
New to DbContext API.
|
Code First Model Building |
n/a | Reads classes and code-based configurations to build (代碼先行) |
New to DbContext API.
|
通過上面表格的介紹,我們應該可以明白 DBContext DBSet 的作用了。
如何在我們的項目中使用DBContext呢?我們可以使用NuGet工具,來獲取DBContext,NuGet工具我已經在前面的博文中進行了介紹(大家也可以通過百度來查一下)。下面附上一張如何使用EF4.3的圖(即如何添加包含DBContext的引用)。
一、DBContext API的一些亮點
DBContext API 主要是針對實體框架交互的簡化。DBContext API相對於以前的實體框架(EF)版本減少了方法和屬性的數量。優化了數據查詢及實體操作方面的功能。下面我們通過一些實例來看看,DBContext API是如何簡化的優化的。交且我們會也 ObjectContext API 進行一些直觀的對比。
(1)、ObjectContext 例子

1 public class BreakAwayContext : ObjectContext 2 { 3 private ObjectSet<Person> _ people; 4 private ObjectSet<Destination> _destinations; 5 private ObjectSet<Trip> _trips; 6 public ObjectSet<Person> People 7 { 8 get { return _people ?? (_people = CreateObjectSet<Person>("People")); } 9 } 10 public ObjectSet< Destination > Contacts 11 { 12 get { return _ destinations?? (_destinations =
13 CreateObjectSet< Destination >("Destinations")); } 14 } 15 public ObjectSet<Trip> Trips 16 { 17 get { return _ trips?? (_trips = CreateObjectSet<Trip>("Trips")); } 18 } 19 }
代碼中顯示了一個用EF4定義的BreakAwayContext類,它繼續ObjectContext。它將子集包裝成ObjectSets類型。
這么說大家可能有點糊塗,我來講的通俗點,BreakAwayContext就相當於一個大的容器,它里面裝着從ObjectContext中繼承來的實體操作方法。同時,它里面還裝着實體子集(其實就是數據庫中對應的表,比如Student表,Teacher表),這些子集的類型是ObjectSet,有了這些子集后,在與數據庫的會話中,我們便可以對其進行操作,來獲取我們自己想要的數據。上面的代碼展示了老版本中的ObjectContext 的應用實例。
(2)、DBContext的例子

1 public class BreakAwayContext : DbContext 2 { 3 public DbSet<Person> People { get; set; } 4 public DbSet<Destination> Destinations { get; set; } 5 public DbSet<Trip> Trips { get; set; } 6 }
對比中發現,DBContext 它將子集包裝成DBSet類型。DBContext使用代碼更加整潔,在DBContext中CreateDbSet與CreateObjectSet有着一樣的功能。
(3)、方法上的改進
ObjectContext和ObjectSet都提供了AddObject的功能:
比如 context.AddObject("Students", newStudent):
context.Students.AddObject(newStudent):
而 DBContext中則只有DBSet有這個功能,並且名稱為成了Add
context.Students.Add(newStudent):
對比發現,Add的操作本身就是對實體的操作,但是ObjectContext和ObjectSet中都有AddObject方法,實在是有點不直觀並且還有點多余。所以DBContext中對他進行了簡化,就只能DBSet中有Add的方法。
(4)、單條實體記錄的查詢改進。(即我們根據ID來查詢一條記錄)
context.People.SingleOrDefault(p => p.PersonId == _personId)
這是早期我們比較長用到的一上方法,但是DBSet給我們提供了更為簡潔的方法,如下:
context.People.Find(_personId)
怎么樣,簡單吧!但是有一點要強調,_personId 要求是主鍵,只有這樣,才可以使用Find方法。
還有一個優點:SingleOrDefault方法會直接執行數據庫查詢,而Find剛會先去緩存中查詢,如果沒有的話,才執行數據庫查詢。感覺不錯吧。
(5)、DBCotext 中查詢
遍歷全部
private static void PrintAllDestinations() { using (var context = new BreakAwayContext()) { foreach (var destination in context.Destinations) { Console.WriteLine(destination.Name); } } }
排序
private static void PrintAllDestinationsSorted() { using (var context = new BreakAwayContext()) { var query = from d in context.Destinations orderby d.Name select d; foreach (var destination in query) { Console.WriteLine(destination.Name); } } }
本地查詢 (會去緩存找是否存在用戶想要的數據)
private static void GetLocalDestinationCount() { using (var context = new BreakAwayContext()) { var count = context.Destinations.Local.Count; Console.WriteLine("Destinations in memory: {0}", count); } }
使用Load 方法將數據放入緩存中
private static void GetLocalDestinationCountWithLoad() { using (var context = new BreakAwayContext()) { context.Destinations.Load(); var count = context.Destinations.Local.Count; Console.WriteLine("Destinations in memory: {0}", count); } }
我們也可以把一些查詢結果也放入到緩存中,同樣是使用Load方法
private static void LoadAustralianDestinations() { using (var context = new BreakAwayContext()) { var query = from d in context.Destinations where d.Country == "Australia"
select d; query.Load(); var count = context.Destinations.Local.Count; Console.WriteLine("Aussie destinations in memory: {0}", count); } }
延遲加載
private static void TestLazyLoading() { using (var context = new BreakAwayContext()) { var query = from d in context.Destinations where d.Name == "Grand Canyon"
select d; var canyon = query.Single(); Console.WriteLine("Grand Canyon Lodging:"); if (canyon.Lodgings != null) { foreach (var lodging in canyon.Lodgings) { Console.WriteLine(lodging.Name); } } } }
關於延遲加載我必須強調一上,延遲加載的使用必需要保證在一下數據庫連接打來的情況下。就是在using(){ 對延遲加載的實體只能在這個范圍中使用,因為數據庫連接一旦關閉,則無法使用了。 }
預先加載 (請注意Include方法)
private static void TestEagerLoading() { using (var context = new BreakAwayContext()) { var allDestinations = context.Destinations.Include(d => d.Lodgings); foreach (var destination in allDestinations) { Console.WriteLine(destination.Name); foreach (var lodging in destination.Lodgings) { Console.WriteLine(" - " + lodging.Name); } } } }
好了,今天就選寫這么多,后續還會寫DBContext之二,進行知識補充。由於寫文字進行說明太費時,有的時候還容易導致大家理解錯誤。所以我主要以代碼來進行說明。希望對大家有用,我是百靈。
百靈注:本文版權由百靈和博客園共同所有,轉載請注明出處。
助人等於自助! mbailing@163.com