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


     

    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给我们提供了许许多多非常灵活的功能,如果我们都能合理利用的话,性能会得到很大的提升。当然,我讲的还不够全面,我会在后续继续跟进。有不足的地方请大家告诉我。  

     

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

    助人等于自助!  mbailing@163.com

     

         

  • 相关阅读:
    struct{} //长篇更新
    channel //长篇更新
    切片 //长篇更新
    引用
    核心:数据篇
    ARM指令解析
    arm寄存器解析
    Java-Selenium,获取下拉框中的每个选项的值,并随机选择某个选项
    log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
    eclipse安装springsource-tool-suite遇到的问题及解决方案
  • 原文地址:https://www.cnblogs.com/mbailing/p/2616779.html
Copyright © 2020-2023  润新知