Свойство навигации каркаса сущности далее фильтруется без загрузки в память - PullRequest
0 голосов
/ 18 июня 2010

У меня есть две сущности с отношением от 1 к N между ними. Давайте скажем Книги и Страницы. Книга имеет свойство навигации как Страницы. Book имеет идентификатор BookId в качестве идентификатора, а Page имеет автоматически сгенерированный идентификатор и скалярное свойство с именем 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();
}

Это работает. Тем не менее, поскольку свойство Pages в Book является EntityCollection, оно должно загрузить все страницы книги в памяти, чтобы получить одну страницу (это замедляет приложение, когда эта функция запускается впервые для данной книги). Т.е. Framework не объединяет запросы и не запускает их сразу. Он загружает страницы в память, а затем использует LINQ для объектов для выполнения второй части

Чтобы преодолеть это, я изменил код следующим образом

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

Это работает значительно быстрее, однако не учитывает страницы, которые не были сериализованы в БД.

Итак, оба варианта имеют свои минусы. Есть ли какая-то хитрость в рамках преодоления этой ситуации. Это должен быть распространенный сценарий, когда вы не хотите, чтобы все объекты свойства Navigation загружались в память, когда они вам не нужны.

1 Ответ

0 голосов
/ 18 июня 2010

Trick?Помимо «Попробовать оба?»

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...