Как заставить метод внутри IQueryable оценить? - PullRequest
0 голосов
/ 25 октября 2019

Я пытаюсь создать сложный запрос LINQ без его выполнения. Прямо сейчас это выглядит так:

// model is EF database context, and Runs/Labs are tables in this database, labNames is array of strings
var sortedGroupsQuery = model.Runs.Where(modelRun =>
                labNames.Select(lab => model.Labs.FirstOrDefault(modelLab => modelLab.name == lab).id).Contains(modelRun.lab_id.Value)
                && modelRun.scenarios.name.StartsWith("Full"))
            .SortByBuildNumberAndId(ShowMasterBranchOnly)
            .GroupBy(modelRun => modelRun.lab_id)
            .Select(group => group.AsQueryable().SortByBuildNumberAndId(ShowMasterBranchOnly));

SortByBuildNumberAndId выглядит так:

public static IOrderedQueryable<AutotestResultService.Runs> SortByBuildNumberAndId(
            this IQueryable<AutotestResultService.Runs> query, bool showMasterBranchOnly) =>
            showMasterBranchOnly
                ? query.Where(modelRun => modelRun.build_number != "NO BUILD NUMBER")
                    .OrderByDescending(modelRun => modelRun.build_number)
                    .ThenByDescending(modelRun => modelRun.id)
                : query.OrderByDescending(modelRun => modelRun.id);

Когда я пытаюсь материализовать запрос в sortedGroupsQuery, я получаю следующую ошибку:

"LINQ to Entities не распознает метод 'System.Linq.IOrderedQueryable`1 [AutotestResultService.Runs] SortByBuildNumberAndId (System.Linq.IQueryable`1 [AutotestResultService.Runs], метод Boolean)этот метод не может быть переведен в выражение хранилища. "

Мне нужно отсортировать содержимое каждой группы. Как заставить его оценить SortByBuildNumberAndId вызов на Where и OrderBy вызовы?

Редактировать

Если удалить последний Select вызов,запрос работает нормально. Это SortByBuildNumberAndId отлично работает при вызове после Where, но по некоторым причинам не будет работать внутри Select. Есть ли способ это исправить? Все, что мне нужно, это отсортировать или отфильтровать содержимое группы на основе значения переменной bool.

Редактировать 2

Это также работает, то есть само по себе SortByBuildNumberAndId правильно:

var sortedGroupsQuery = model.Runs.Where(modelRun =>
                    labNames.Select(lab => model.Labs.FirstOrDefault(modelLab => modelLab.name == lab).id)
                        .Contains(modelRun.lab_id.Value)
                    && modelRun.scenarios.name.StartsWith("Full"))
                //.ApplyFilters(ShowMasterBranchOnly, BuildNumber, ShowVDP)
                .SortByBuildNumberAndId(ShowMasterBranchOnly)
                .GroupBy(modelRun => modelRun.lab_id)
                .Select(group => group.AsQueryable()
                    .Where(modelRun => modelRun.build_number != "NO BUILD NUMBER")
                    .OrderByDescending(modelRun => modelRun.build_number)
                    .ThenByDescending(modelRun => modelRun.id));

Редактировать 3: В целях тестирования я попытался добавить это:

public static IQueryable<AutotestResultService.Runs> SortByBuildNumberAndId(
    this IQueryable<AutotestResultService.Runs> query) =>
    true
        ? query.Where(modelRun => modelRun.build_number != "NO BUILD NUMBER")
            .OrderByDescending(modelRun => modelRun.build_number)
            .ThenByDescending(modelRun => modelRun.id)
        : query.OrderByDescending(modelRun => modelRun.id);

И это:

public static IQueryable<AutotestResultService.Runs> SortByBuildNumberAndId(
            this IQueryable<AutotestResultService.Runs> query) =>
                query.Where(modelRun => modelRun.build_number != "NO BUILD NUMBER")
                    .OrderByDescending(modelRun => modelRun.build_number)
                    .ThenByDescending(modelRun => modelRun.id);

Оба выиграли 'работает с той же ошибкой:

var sortedGroupsQuery = model.Runs.Where(modelRun =>
                    labNames.Select(lab => model.Labs.FirstOrDefault(modelLab => modelLab.name == lab).id)
                        .Contains(modelRun.lab_id.Value)
                    && modelRun.scenarios.name.StartsWith("Full"))
                .SortByBuildNumberAndId(ShowMasterBranchOnly)
                .GroupBy(modelRun => modelRun.lab_id)
                .Select(group => group.AsQueryable().SortByBuildNumberAndId());

1 Ответ

1 голос
/ 25 октября 2019

Вы должны построить запрос, а не пытаться определить его все сразу.


Main
{
   var query = model.Runs.Where(...);
   query = AddSortLogic(query);
   var finalQuery = query.GroupBy(...).Select(...);
}

private IQueryable<Runs> AddSortLogic(IQueryable<Runs> query)
{
   if(ShowMasterBranchOnly)
   {
      query = query.Where(...)
         .SortBy(...)
         .ThenBy(...);
   }
   else
   {
      query = query.SortBy(...);
   }
   return query;
}
...