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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值