2010-10-14 2 views
0

Примечание: Я знаю, что существует ряд вопросов по вопросам, связанным с проблемами Linq. Включение (таблица), не загружающее данные, я считаю, что исчерпал опции, которые люди перечисляли, и все еще были проблемы.Linq2Entities Include with Skip/Take-load issue

У меня есть большой запрос Linq2Entities для приложения, которое я поддерживаю. Запрос строится так:

IQueryable<Results> query = context.MyTable 
    .Where(r => 
    r.RelatedTable.ID == 2 && 
    r.AnotherRelatedTable.ID == someId); 

Тогда предикаты построены в зависимости от различных бизнес-логики, такие как:

if (sortColumn.Contains("dob ")) 
{ 
    if (orderByAscending) 
     query = query.OrderBy(p => p.RelatedTable.OrderByDescending(q => q.ID).FirstOrDefault().FieldName); 
    else 
     query = query.OrderByDescending(p => p.RelatedTable.OrderByDescending(q => q.ID).FirstOrDefault().FieldName); 
} 

Примечание - всегда есть порядок сортировки при условии.

Первоначально включены таблицы были установлены в начале, после прочтения статьи, такие как знаменитый Tip 22, так что теперь они сделаны в конце (который не решить эту проблему):

var resultsList = (query.Select(r => r) as ObjectQuery<Results>) 
    .Include("RelatedTable") 
    .Include("AnotherRelatedTable") 
    .Skip((page - 1) * rowsPerPage) 
    .Take(rowsPerPage); 

Казалось бы, в random (приблизительно для каждых 5000 пользователей сайта, эта проблема возникает один раз), данные RelatedTable не загружаются. Это может быть грубо принудительно, вызвав нагрузку на связанную таблицу. Но даже сбой при загрузке несовместим, я запускаю запрос при тестировании, и он работает, но в большинстве случаев он не меняет никакого кода или данных.

Это нормально, когда пропуск и прием не включены, и весь набор данных возвращается, но я бы ожидал пропустить и сделать это на полном наборе данных - это, безусловно, связано с профилированием SQL ...

ОБНОВЛЕНИЕ 16/11/10: Я профилировал SQL против набора данных проблемы, и я смог воспроизвести запрос с ошибкой около 9/10 раз, но в итоге остальное. Выполняемый SQL идентичен, когда запрос терпит неудачу или преуспевает, за исключением, как и ожидалось, параметров, переданных в SQL.

Вопрос был решен со следующим изменением, но остается вопрос, почему это должно быть.

В противном случае - получить LINQ для обработки строк:

var resultsList = (query.Select(r => r) as ObjectQuery<Results>) 
    .Include("RelatedTable") 
    .Include("AnotherRelatedTable") 
    .Skip((page - 1) * rowsPerPage) 
    .Take(rowsPerPage) 
    .ToList(); 

Working - перечислить данные затем получить строки:

var resultsList = (query.Select(r => r) as ObjectQuery<Results>) 
    .Include("RelatedTable") 
    .Include("AnotherRelatedTable") 
    .ToList() 
    .Skip((page - 1) * rowsPerPage) 
    .Take(rowsPerPage); 

К сожалению, SQL создает этот запрос содержит некоторые важные данные схемы, так что я не может опубликовать его, это также 1400 строк, поэтому я бы не стал публиковать его в любом случае!

+0

Это L2E или L2SQL? –

+0

Извините, L2E ... не знаю, почему я писал L2SQL! – Timbo

+0

Значит, вы говорите, что SQL - это то же самое для рабочего запроса запроса и запроса запроса, который терпит неудачу? –

ответ

2

Единственным эффектом Take() является изменение сгенерированного SQL. Помимо этого, Entity Framework не заботится об этом вообще. То же самое для .Skip(). Трудно поверить, что это повлияет на материализацию запросов (хотя произошли более странные вещи).

А что такое может вызвать такое поведение? В верхней части головы:

  1. Ошибка в вашем приложении или отображение, которое вызывает неправильный запрос.
  2. Ошибка в инфраструктуре Entity Framework, которая привела бы к тому, что возвращенные данные были бы материализованы в объекты некорректно при определенных обстоятельствах.
  3. Плохие данные в вашей базе данных.
  4. Ошибка в парсе базы данных SQL.

Я не думаю, что вы получите намного больше, пока не сможете захватить сгенерированный SQL и запустить его самостоятельно. Это на самом деле не очень сложно, так как вы можете настроить профилировщик SQL с соответствующим фильтром. Если вы обнаружите, что сгенерированный SQL отличается в случае с ошибкой, вы можете отступить оттуда назад. Если вы обнаружите, что сгенерированный SQL идентичен в случае с ошибкой, следующим шагом будет просмотр возвращаемых строк, предпочтительно в том же контексте, что и приложение.

Короче говоря, я думаю, вам просто нужно настроить настройку SQL, пока у вас нет необходимой информации.

+1

Я бы переместил номер 3 над номером 2. Если вы сомневаетесь, предположите, что ваш код/​​данные ошибочны, а не ваши инструменты. – tster

+0

@tster: Полностью согласовано. –

+0

Спасибо Крейг. Я не мог согласиться с тем, что наиболее вероятным ответом являются мои данные. Интересно, что в настоящее время я работал над этим, перечислив запрос в список, затем выполнив пропуски и включись в список. Это прекрасно работает ... не уверен, что это значит для этого! Я собираюсь попробовать еще раз, чтобы профилировать хороший/плохой запрос в течение следующих нескольких дней, я согласен в принципе, что это лучший вариант, но, как правило, сгенерированный sql имеет длину 2000 строк. Кто-то выбрал неправильный инструмент для работы, которую я считаю! : P – Timbo