代码之家  ›  专栏  ›  技术社区  ›  cellik

实体框架导航属性进一步筛选而不加载到内存中

  •  0
  • cellik  · 技术社区  · 14 年前

    我有两个实体,它们之间有1到n的关系。比如书籍和书页。 Book具有作为页面的导航属性。book以book id作为标识符,page具有自动生成的id和名为pageno的标量属性。Lazyloading设置为true。

    我使用VS2010&NET 4.0生成了这个,并从中创建了一个数据库。 在书的部分类中,我需要像下面这样的getpage函数

    public Page GetPage(int PageNumber)
    {
         //checking whether it exist etc are not included for simplicity
         return Pages.Where(p=>p.PageNo==PageNumber).First();
    }
    

    这是可行的。但是,由于书籍中的Pages属性是一个EntityCollection,因此必须将书籍的所有页面加载到内存中才能获得一个页面(对于给定的书籍,当首次点击此函数时,这会减慢应用程序的速度)。也就是说,框架不会合并查询并立即运行它们。它将页面加载到内存中,然后使用Linq to对象执行第二部分。

    为了克服这个问题,我修改了下面的代码

      public Page GetPage(int PageNumber)
        {
              MyContainer container = new MyContainer();
              return container.Pages.Where(p=>p.PageNo==PageNumber && p.Book.BookId==BookId).First();
        }
    

    这样做的速度要快得多,但是它没有考虑到尚未序列化到数据库的页面。

    所以,这两种选择都有其缺点。框架中是否存在克服这种情况的技巧。这必须是一个常见的场景,当您不需要导航属性的所有对象时,您不希望它们都加载到内存中。

    1 回复  |  直到 14 年前
        1
  •  0
  •   Craig Stuntz    14 年前

    诀窍?除了“两个都试试?”

    public Page GetPage(int pageNumber)
    {
         // check local values, possibly not persisted yet. 
         // works fine if nothing loaded.
         var result = Pages.Where(p => p.PageNo == pageNumber).FirstOrDefault();
         if (result != null) 
         {
             return result;
         }
         // check DB if nothing found
         MyContainer container = new MyContainer();
         return container.Pages.Where(p => p.PageNo == pageNumber && p.Book.BookId==BookId).First();
    }
    

    除了通过pk值加载的特定情况外,没有什么可以自动执行此操作,您可以使用 ObjectContext.[Try]GetObjectByKey .