Entity Framework 4.1/4.3 之五 (DBContext 之 2 查询功能)

 

Entity Framework 4.1/4.3 之五 (DBContext 之 2 查询功能)

 

  昨天我们讲了 DBContext的作用及它的一些相对于ObjectContext进行的优化,今天继续进行补充。我们还是用代码来说明,文章中会加入大量的代码。对了,伦敦奥运第三日,中国军团再添3金,了不起。

    

      一、DBContext 的查询功能 (Querying with DBContext)

 

       (1)、显示加载

            前面我们已经讲过了延迟加载和预加载,这回我们来讲讲显示加载。光数据加载都整出这么多种方式。(真TMD的Fuck,此处是个人情感的发泄)

            显示加载:显示加载与延迟加载很相似,都是主从数据加载分离。但不同的是,延迟加载会自动加载从数据,而显示加载我们必需要通过一个方法来明确我们要加载的数据。上菜:

            显示加载使用的方法是 DBContext.Entry 方法。

      private static void TestExplicitLoading()       {         using (var context = new BreakAwayContext())         {           var query = from d in context.Destinations                  where d.Name == "Grand Canyon"

                 select d;           var canyon = query.Single();           context.Entry(canyon).Collection(d => d.Lodgings).Load();           Console.WriteLine("Grand Canyon Lodging:");           foreach (var lodging in canyon.Lodgings)           {             Console.WriteLine(lodging.Name);           }         }       }

     从代码中可以看到,使用Entry方法来显示加载canyon,然后能加导航属性(Lodgings)来加载关联表的数据集合。可能大家对导航属性有的模糊,其实就是表和表之前的关系。比如Class 与 Student的关系是一对多的关系,一个班有多个学生。在Entity Framework中,这种关系我们称之为导航属性。当然,也有一对一的关系。多对多的关系。

 

        (2)、显示加载中,如何确定导航属性是否被加载

             IsLoaded 方法可以来判断关联表数据是否被加载(即导航属性),也就是说是否从数据库中取得了数据。
                

      private static void TestIsLoaded()       {         using (var context = new BreakAwayContext())         {           var canyon = (from d in context.Destinations                   where d.Name == "Grand Canyon"

                  select d).Single();           var entry = context.Entry(canyon);           Console.WriteLine(           "Before Load: {0}",             entry.Collection(d => d.Lodgings).IsLoaded);             entry.Collection(d => d.Lodgings).Load();             Console.WriteLine(           "After Load: {0}",             entry.Collection(d => d.Lodgings).IsLoaded);         }       }
输出的结果是:Before Load: False
             After Load: True

           

   二、DBContext对于实体的增、删、改  (Adding, Changing, and Deleting Entities)
         

           (1)、单条记录的处理

              1.1、增加一条新记录

      private static void AddMachuPicchu()       {         using (var context = new BreakAwayContext())         {           var machuPicchu = new Destination           {             Name = "Machu Picchu",             Country = "Peru"           };           context.Destinations.Add(machuPicchu);           context.SaveChanges();         }       }

               可以注意到,使用了BDSet<>.Add的方法,Destinations.Add(machuPicchu); Destinations是DBSet类型。

 

               1.2、修改一条记录

      private static void ChangeGrandCanyon()       {         using (var context = new BreakAwayContext())         {           var canyon = (from d in context.Destinations                    where d.Name == "Grand Canyon"

                  select d).Single();           canyon.Description = "227 mile long canyon.";           context.SaveChanges();         }       }

              这里我们要提到一个批量操作的概念,就是我们可以同时新增并且对一条记录进行修改,我们来看代码:

    private static void MakeMultipleChanges()     {       using (var context = new BreakAwayContext())
      {         var niagaraFalls = new Destination         {           Name = "Niagara Falls",           Country = "USA"         };         context.Destinations.Add(niagaraFalls);         var wineGlassBay = (from d in context.Destinations                   where d.Name == "Wine Glass Bay"                   select d).Single();         wineGlassBay.Description = "Picturesque bay with beaches.";         context.SaveChanges();       }     }

我们来看看它发送到数据库执行的语句:可以看到同时实现了新增和编辑。这就是批量操作。

 

      1.3、删除一条记录

      private static void DeleteWineGlassBay()       {         using (var context = new BreakAwayContext())         {           var bay = (from d in context.Destinations                  where d.Name == "Wine Glass Bay"

                 select d).Single();           context.Destinations.Remove(bay);           context.SaveChanges();         }       }

       关于删除操作,我们要多讲讲,因为有的时候我们会去新增加的实体进行删除操作。有的时候我们也会对多表进行关联删除。那么这些情况下,Remove是如何实现的呢?我来一一分析。


       先来看看删除的在理:我们先通过条件来找到一个对象,然后BDContext会对应该对象建立状态跟踪。删除时,对象必须被跟踪的更改跟踪标记为删除,savechanges建造一个删除命令发送到数据库,然后热行删除。

 

        如果你知道你需要删除的实体,但没有执行查询来找它(也就是说,它不存在内存中),DBContext给我们提供了一个很好的操作,我们可以直接从数据库中来删除这条记录。步骤是可以添加一个替身实体,并删除这个替身实体,这时候BDContext会更改其状态为删除,savechanges建造一个删除命令发送到数据库,然后热行删除。我们来看代码:

  var toDelete = new Destination { DestinationId = 2 };   context.Destinations.Attach(toDelete);   context.Destinations.Remove(toDelete);   context.SaveChanges();

        我们通知Key DestinationId知道要删除的实体,Attach添加替身,Remove替身,SaveChanges(告诉数据库执行删除)。是不是很方便,减少了一次与数据库的交互,就是查找实体那一步。如果内在中有该实体的话,刚不能使用Attach方法,否则会报错。

        当然,我们还可以利用Sql语句来执行删除,DBContext同样能办到,代码如下:

  context.Database.ExecuteSqlCommand("DELETE FROM baga.Locations WHERE LocationName = 'Hawaii'");

 


         关联删除,即对有主从关系的实体进行关联删除,我们还是直接来看代码:

        

  private static void DeleteGrandCanyon()   {     using (var context = new BreakAwayContext())     {       var canyon = (from d in context.Destinations               where d.Name == "Grand Canyon"

              select d).Single();       context.Entry(canyon)       .Collection(d => d.Lodgings)       .Load();       context.Destinations.Remove(canyon);       context.SaveChanges();     }   }

 

  这是上面关联删除发送到数据库所执行的三条语句,实现了主从删除。

      

     好了,我是百灵,我今天就先写到这里,我们看到了DBContext给我们提供了许许多多非常灵活的功能,如果我们都能合理利用的话,性能会得到很大的提升。当然,我讲的还不够全面,我会在后续继续跟进。有不足的地方请大家告诉我。  

 

百灵注:本文版权由百灵和博客园共同所有,转载请注明出处。      

助人等于自助!  [email protected]

 

     

你可能感兴趣的:(framework)