Linq2Entities Включить с Skip / Take - проблема загрузки - PullRequest
0 голосов
/ 14 октября 2010

Примечание. Я знаю, что существует ряд вопросов по поводу проблем, связанных с тем, что Linq .Include (таблица) не загружает данные. Я полагаю, что я исчерпал варианты, перечисленные людьми, и все еще имел проблемы.

У меня большой запрос 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);
}

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

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

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

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

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

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

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

Failing - получить 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 строк, так что я бы не стал их публично выставлять!

1 Ответ

2 голосов
/ 15 октября 2010

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

Так что же может вызывать такое поведение? С макушки головы:

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

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

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

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