Entity Framework 4.1/4.3 之四(DBContext 之 1 DBContext 是誰)


 

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
API feature (DbContext API功能)

Relevant EF4
feature/class (有關EF4中的功能/類)
General purpose(共同的作用) Benefit of DbContext API (DBContext API 的優勢)
DbContext ObjectContext

Represent a session with the database. Provide
query, change tracking and save capabilities

(與數據庫進行會話)

Exposes and simplifies most
commonly used features of ObjectContext.

(簡化ObjectContext中的常用功能)

DbSet ObjectSet

Provide set operations for entity types, such as Add,
Attach and Remove. Inherits from DbQuery to expose
query capabilities.

(提貨對數據實體的操作,如增、改、查,繼承了DBQuery的一些功能)

Exposes and simplifies most
commonly used features of ObjectSet.

(簡化ObjectSet中的常用功能)

DbQuery ObjectQuery

Provide querying capabilities

(提供查詢功能)

The query functionality of
DbQuery is exposed on DbSet, so
you don’t have to interact with
DbQuery directly.

()

Change
Tracker API
ObjectContext.
ObjectStateManager

Get access to change tracking information and operations
(e.g., original values, current values) managed
by the context.

(獲取發生的跟蹤信息和操作(例如,原始值,當前值)並進行管理。)

Simpler and more intuitive API
surface.

(簡化更多API使用)

Validation API n/a

Provide automatic validation of data at the data
layer. This API takes advantage of validation features
already existing in .NET 4.

(提供自動化的數據驗證,驗證功能在.Net4已經存在)

New to DbContext API.

 

Code First
Model
Building
n/a

Reads classes and code-based configurations to build
in-memory model, metadata and relevant database.

(代碼先行)

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 例子

        View Code
 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的例子

      View Code
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

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM