Entity Framework 4.1/4.3 之六 (DBContext 之 3 狀態跟蹤 )


 

Entity Framework 4.1/4.3 之六 (DBContext  之 3 狀態跟蹤)

 

  咱們接着來講DBContext,這回內容將與DBContext 2中所講的內容連貫起來。

 

  二、DBContext對於實體的增、刪、改  (Adding, Changing, and Deleting Entities)

      DBContext 2中我們講到了“增、刪、改”,其中已經講了“增、刪、改”。還有部分內容沒講,我們補全。

       

      (1)、查找增加模式 (The “Find or Add” Pattern)

        場景:我們常常會增加一條記錄,增加的步驟是先查找有沒有相同記錄存在,如果不存在內里將新記錄新增到數據庫中。在老版EF中我們會執行兩次操作:即先找,在增。這無形中要與數據庫交互兩。

        DBContext為我們提供了新的解決方案,即Find or Add,我們來看看代碼:

    private static void FindOrAddPerson()     {       using (var context = new BreakAwayContext())       {         var ssn = 123456789;         var person = context.People.Find(ssn)?? context.People.Add(new Person         {           SocialSecurityNumber = ssn,           FirstName = "jerry",           LastName = "tom"         });         Console.WriteLine(person.FirstName);       }     }

    代碼看起來非常的直觀,如果Find(ssn)在緩存或者數據庫中找到了該記錄,則輸出,否則則新增一條記錄。

 

        (2)、新增關系數據(Adding a Relationship Between Objects)

        說實話,這個理解起來有點繞,不好解釋。我們還是直接來看下面的代碼吧!

    private static void NewGrandCanyonResort()     {       using (var context = new BreakAwayContext())       {         var resort = new Resort         {           Name = "Pete's Luxury Resort"         };         context.Lodgings.Add(resort);         var canyon = (from d in context.Destinations                 where d.Name == "Grand Canyon"
                select d).Single();         canyon.Lodgings.Add(resort);         context.SaveChanges();       }     }

    Destinations 與 Lodgings 是一對多的關系,首先我們創建一個 resort 對象,將它加入到 Lodgings 集合中。然后我們找到父集合Destinations ,將resort 對象加入到Destinations包含的Lodgings集合中,然后SaveChanges,這種關聯關系就建立起來了,相應的數據也保存到了數據庫中。就是這么個意思,通俗的講,就是先在從表里增加一條記錄,然后將新增的記錄與主表關系起來。你明白了嗎?

        這里我要強調一點,兩表關聯,對應該的關系ID要統一。比如主表中的主鍵是 classId ,那么相關系的從表關聯id 也應該是classId,如果不統一的話,EF很難自動進行Map,除非人為的在Map文件中重改映射關系。

 

    (3)、修改關系數據 (Changing a Relationship Between Objects)

      private static void ChangeLodgingDestination()       {         using (var context = new BreakAwayContext())         {           var hotel = (from l in context.Lodgings                   where l.Name == "Grand Hotel"
                  select l).Single();           var reef = (from d in context.Destinations                   where d.Name == "Great Barrier Reef"
                  select d).Single();           hotel.Destination = reef;           context.SaveChanges();         }       }

這是生成Sql語句:
    exec sp_executesql N'update [dbo].[Lodgings]
    set [destination_id] = @0
    where ([LodgingId] = @1)
    ',N'@0 int,@1 int',@0=4,@1=1

       這里Lodgings依然扮演着從表的角色,代碼暫示了主從表關系的變更。當然,這只是DBContext中給我們提供的一個解決方案。我個人習慣直接修改關聯關系ID的值。

 

    (4)、刪除關系(Removing a Relationship Between Objects)

      private static void RemovePrimaryContact()       {         using (var context = new BreakAwayContext())         {           var davesDump = (from l in context.Lodgings                     where l.Name == "Dave's Dump"
                    select l).Single();           context.Entry(davesDump).Reference(l => l.PrimaryContact).Load();           davesDump.PrimaryContact = null;           context.SaveChanges();
        }       }

 

      private static void RemovePrimaryContact()       {         using (var context = new BreakAwayContext())         {           var davesDump = (from l in context.Lodgings                     where l.Name == "Dave's Dump"
                    select l).Single();           davesDump.PrimaryContactId = null;           context.SaveChanges();         }       }

               刪除關系沒什么好講的,一種方式是關聯子集置空,一種方式是將關聯id置空。


            (5)、簡單描述一下跟蹤狀態,這里只是簡單的了解,后續會有專門的詳解。(Working with Change Tracking)

               狀態清單:• DbSet.Add
           • DbSet.Find
           • DbSet.Remove
           • DbSet.Local
           • DbContext.SaveChanges
           • Running any LINQ query against a DbSet
           • DbSet.Attach
           • DbContext.GetValidationErrors
           • DbContext.Entry
           • DbChangeTracker.Entries

              正是有了這些跟蹤狀態(Tracking),SaveChanges才知道它應該干些什么。

      

      DetectChanges:變化檢測(Controlling When DetectChanges Is Called) 控制程序將在 變化檢測時被觸發。

           大多數情況下(或者說大多說時間),在SaveChanges期間 Entity Framework 都需要知道 Tracking Change(即跟蹤狀態的改變情況)。     這里有個不太好理解的定義:Automatic DetectChanges 下面是一段應用代碼,因為目前我對Automatic DetectChanges還不太准確。所以只把代碼展示出來,大家分析分析。      

      private static void ManualDetectChanges()       {         using (var context = new BreakAwayContext())         {           context.Configuration.AutoDetectChangesEnabled = false;           var reef = (from d in context.Destinations                   where d.Name == "Great Barrier Reef"
                  select d).Single();           reef.Description = "The world's largest reef.";           Console.WriteLine(             "Before DetectChanges: {0}",               context.Entry(reef).State);               context.ChangeTracker.DetectChanges();               Using Snapshot Change Tracking | 61           Console.WriteLine(             "After DetectChanges: {0}",               context.Entry(reef).State);         }       }

              

      private static void AddMultipleDestinations()       {         using (var context = new BreakAwayContext())         {           context.Configuration.AutoDetectChangesEnabled = false;           context.Destinations.Add(new Destination           {             Name = "Paris",             Country = "France"           });
          context.Destinations.Add(new Destination           {             Name = "Grindelwald",             Country = "Switzerland"           });           context.Destinations.Add(new Destination           {             Name = "Crete",             Country = "Greece"           });           context.SaveChanges();         }       }

     我總覺得這個很難理解。

    (6)、使用detectchanges觸發關系 (Using DetectChanges to Trigger Relationship Fix-up) (這個也是我目前不太理解的,下面是實例中的代碼)

      private static void DetectRelationshipChanges()       {         using (var context = new BreakAwayContext())         {           var hawaii = (from d in context.Destinations                   where d.Name == "Hawaii"
                  select d).Single();           var davesDump = (from l in context.Lodgings                   where l.Name == "Dave's Dump"
                  select l).Single();           context.Entry(davesDump)               .Reference(l => l.Destination)               .Load();           hawaii.Lodgings.Add(davesDump);           Console.WriteLine(               "Before DetectChanges: {0}",                 davesDump.Destination.Name);                 context.ChangeTracker.DetectChanges();           Console.WriteLine(               "After DetectChanges: {0}",                 davesDump.Destination.Name);         }       }

      希望代碼能讓我們明白其中的道理。

        (7)、啟用和使用更改跟蹤代理 (Enabling and Working with Change Tracking Proxies)

         (8)、確保新實例獲取代理 (Ensuring the New Instances Get Proxies)

         (9)、創建派生類型的代理實例(Creating Proxy Instances for Derived Types)

     (10)、不更改跟蹤獲取實體 (Fetching Entities Without Change Tracking)

       

         小述:6、7、8、9、10 這幾種方式我沒有用到,也不知道他們有什么好處和優點。如果大家了解的話,請告訴我。我先將自己用過和理解的寫錯來。對於一些未知的領域,也希望大家不吝指教。好了,就寫到這里,我是百靈。

 

百靈注:本文版權由百靈和博客園共同所有,轉載請注明出處。
助人等於自助!  mbailing@163.com


免責聲明!

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



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