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

时间:2010-06-18 13:47:36

标签: entity-framework

我有两个实体,中间有1到N的关系。让我们说书籍和页面。 Book有一个导航属性作为Pages。 Book有BookId作为标识符,Page有一个自动生成的id和一个名为PageNo的标量属性。 LazyLoading设置为true。

我使用VS2010& .net 4.0并从中创建了一个数据库。 在Book的部分类中,我需要一个GetPage函数,如下所示

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

这很有效。但是,由于Book中的Pages属性是一个EntityCollection,它必须在内存中加载一本书的所有页面才能获得一个页面(当给定书籍第一次点击此功能时,这会减慢应用程序的速度)。即Framework不会合并查询并立即运行它们。它将Pages加载到内存中,然后使用LINQ to objects来执行第二部分

为了解决这个问题,我改变了代码如下

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

这种方法的工作速度要快得多,但它没有考虑到尚未序列化到数据库的页面。

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

1 个答案:

答案 0 :(得分:0)

圈套?除了“试试两个?”

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