• Entity Framework 4.1/4.3 之六 (DBContext 之 3 状态跟踪 ) jerry


     

    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

  • 相关阅读:
    3、Less-计算
    2、Less-混合
    1、Less-初见
    5、反射-动态代理
    4、反射-类的构造器:Constrctor
    3、反射-Field
    2、反射-Method&父类
    1、反射-Class&ClassLoader
    5、URLConnection(3)
    Linux进程状态查询
  • 原文地址:https://www.cnblogs.com/mbailing/p/2618097.html
Copyright © 2020-2023  润新知