我有两个实体,中间有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();
}
这种方法的工作速度要快得多,但它没有考虑到尚未序列化到数据库的页面。
因此,两种选择都有其缺点。框架中是否有任何技巧可以克服这种情况。这必须是一种常见的情况,您不希望在不需要导航属性的所有对象时将其加载到内存中。
答案 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
。