2013-04-17 2 views
3

У меня есть общий метод базового хранилища для поиска (обрезается для ясности):EF - почему иногда рвутся нагрузки, иногда ленивые нагрузок

public class Repository<TRepository> : IRepository<TRepository> 
     where TRepository : class, IEntity, new() 
{  
    public virtual IQueryable<TRepository> SearchFor(Expression<Func<TRepository, bool>> predicate, Expression<Func<TRepository, bool>> orderbylinq = null) 
    { 
     if (orderbylinq == null) 
     { 
      return DbSet.Where(predicate); 
     } 
     else 
     { 
      return DbSet.Where(predicate).OrderBy(orderbylinq); 
     } 
    } 

} 

У меня есть производный хранилище класс:

public class TimeDetailRepository : Repository<TimeDetail> 

В мои услуги слой, у меня есть класс, который вызывает метод SearchFor:

private TimeDetailRepository _timeDetailRepository; 

     public ManageTimeDetailsAppServ() 
      : base(new TimeDetailRepository()) 
     { 
      _timeDetailRepository = new TimeDetailRepository(); 
     } 
IQueryable<TimeDetail> timeDetails2 = _timeDetailRepository.SearchFor(
        x => x.Id == 3214); 

В этом случае timeDetails2 полностью нагрузки ed (все связанные объекты загружаются).

НО, у меня есть еще один класс (базовый уровень услуг класса), что делает тот же SearchFor вызов, пока он не загружает соответствующие объекты:

IQueryable<TRepository> dbEntity = _repository.SearchFor(x => x.Id == result.Value); 

от обоих вызовов я пытаюсь создать которая использует значения свойств из связанных объектов. Зачем загружать их в одном случае, а не в другом? Это тот же объект TimeDetail, тот же базовый класс репозитория?

Изображение того, что вы видите в отладчике. Почему некоторые связанные с ними объекты будут загружены (например, фонда и TimeDetailStatus), а другие нет (как OrderHeader или Заказчик) enter image description here

UPDATE

Я смотрел на запросы генерируются и они оба кажутся похожими, т.е. они не присоединяются к другим таблицам ... так что возможно, что контекст уже содержит некоторые кешированные строки из некоторых связанных объектов, как они становятся включенными?

+0

Что означает название вопроса? – Slauma

+0

обновлено, мы надеемся, что оно яснее –

+1

Может быть, timeDetails2 будет восстановлен в цепочке запросов и ранее уже извлеченных объектов? – LukLed

ответ

4

EF сделает ленивую загрузку, если вы не используете метод .Include() на съемочной площадке. Поскольку вы этого не делаете, вы не получите их немедленно, но вы получите их загруженными лениво, когда вы их вызовете.

Однако это работает только в том случае, если контекст объекта все еще открыт. Если контекст ушел, то ваша способность подключиться к базе данных исчезнет, ​​поэтому ваши свойства будут пустыми.

Я предполагаю, что разница, которую вы видите, связана с тем, как вы поддерживаете контекст. Трудно сказать, потому что вы не показываете, где ваш контекст, но я бы начал там.

EDIT

Не уверен, если это будет иметь ничего общего с вашим вопросом, но я просто хотел уточнить отложенной загрузки материала. Вот мой любимый EF пример: 2 таблицы: Автор (AuthorID, AUTHORNAME) и книги (BookID, AuthorID (FK), BOOKTITLE)

/* 1 */ static void Main(string[] args) 
/* 2 */ { 
/* 3 */ Book book; 
/* 4 */ using (var context = new SampleDbEntities()) 
/* 5 */ { 
/* 6 */  book = context.Books.Single(b => b.BookId == 1); 
/* 7 */ } 
/* 8 */ 
/* 9 */ try 
/* 10 */ { 
/* 11 */  Console.WriteLine(book.Author.AuthorName); 
/* 12 */ } 
/* 13 */ catch (Exception ex) 
/* 14 */ { 
/* 15 */  Console.WriteLine(ex.Message); 
/* 16 */ } 
/* 17 */ 
/* 18 */ Console.ReadLine(); 
/* 19 */ } 

Если запустить этот код, как есть, вот что произойдет:

  • Строка 6 запросит только таблицу Books и заполнит переменную book соответствующей записью. Таблица Authors никогда не затрагивается в базе данных.
  • После строки 7 контекст расположен, что означает, что доступ к данным мертв.
  • Строка 11 выдает исключение, пытающееся получить доступ к свойству Author.

Однако, если вы используете отладчик и остановиться на строке 7, чтобы просто посмотреть на переменные книги для доли секунды, он будет немедленно запросить Authors таблицы в базе данных (в то время как вы находитесь в отладчике) и заполнить свойство Author на этом объекте. Это то, что я подразумеваю под ленивой загрузкой - когда вы действительно получаете доступ к свойству, даже в отладчике, в то время как контекст жив, он вызывает новый вызов базы данных. Теперь вы можете продолжить код, и строка 11 будет прекрасной, и имя автора будет напечатано.

В основном, не доверяйте отладчику, когда дело касается EF. Он лениво загружает данные, даже если он не похож на него. Лучше всего понять, что происходит, это запустить SQL Profiler и посмотреть, какие запросы выполняются.

+0

Joe, спасибо за вход. Я новичок в EF, поэтому я не могу правильно говорить. Я наблюдаю, что результат dbEntity (из моего кода выше) имеет связанные сущности как null, когда я проверяю его в отладчике сразу после установки dbEntity. Таким образом, в контексте нет изменений. Не уверен, что это имеет какое-либо отношение к ленивой и нетерпеливой загрузке ... это именно то, что я предполагал. Извините, я не был более ясен, чтобы начать. –

+0

@ChadRichardson См. Мое правление относительно ленивой загрузки. Этот пример показывает, как код ведет себя по-разному в зависимости от того, когда доступ к ресурсу и насколько жив контекст объекта. –

+0

благодарит Джо за объяснение, но у меня, кажется, есть смесь ... т. Е. некоторые связанные объекты загружаются, а другие нет. Просмотрите мой обновленный вопрос, сняв снимок того, что показывает отладчик. Почему некоторые нагрузки и другие нет? –

Смежные вопросы