Как я могу передать предикат <T>методу Where () в Linq для SQL? - PullRequest
1 голос
/ 11 ноября 2010

У меня есть следующая модель:

 +--------+
 | Folder |
 +--------+
     | 1
     |
     | *
+----------+         +---------+
| WorkItem |---------| Project |
+----------+ *     1 +---------+

Мне нужно получить список папок с текущим количеством WorkItems.

Если я указал проект, то я хочу толькоколичество рабочих элементов в каждой папке, связанных с указанным проектом.

Если проект не указан, он должен вернуть общее количество рабочих элементов.

У меня есть следующий код Linq to SQL:

public interface IWorkItemCriteria {
    int? ProjectId { get; }
}

public static IQueryable<Folder> GetFoldersWithItemCounts(IWorkItemCriteria criteria) {
    var results = from folder in dataContext.Folders
        select new {
              Folder = folder,
              Count = folder.WorkItems.Count()
    };
    return(results);
}

Проблема в том, что я хочу отфильтровать подсчитываемые рабочие элементы.

Это работает:

    var results = from folder in dataContext.Folders
        select new {
              Folder = folder,
              Count = folder.WorkItems.Where(item => item.ProjectId == criteria.ProjectId).Count()
    };

, но я не могу его получитьиспользовать любой вид динамического предиката / выражения.Синтаксис, который я пытаюсь использовать:

    var results = from folder in dataContext.Folders
        select new {
              Folder = folder,
              Count = folder.WorkItems.Where(filter).Count()
    };

Я пробовал

Predicate<WorkItem> filter = (item => item.ProjectId == criteria.ProjectId);

и

Expression<Func<WorkItem, bool>> filter = (item => item.ProjectId == criteria.ProjectId)

, ни один из которых не скомпилируется - дает The type arguments for method 'System.Linq.Enumerable.Where<TSource> (System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

Я пробовал

Func<WorkItem, bool> filter = (item => item.ProjectId == criteria.ProjectId);

, который строит, но затем завершается неудачно с 'Неподдерживаемая перегрузка, используемая для оператора запроса' Где '.'

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

Есть идеи?

Ответы [ 2 ]

1 голос
/ 14 ноября 2010

Я думаю, что ваша проблема в том, что вы хотите сослаться на одно выражение (фильтр) из второго выражения (которое передается в results.Where.Select ()), и что поставщик LINQ to SQL IQueryable не 'не знаю, как получить значение этого значения.

То, что вам нужно сделать, это составить выражение Select с нуля, чтобы inline выражение, которое является вашим динамическим фильтром.Это может быть очень сложно с анонимными типами, я не уверен.Я только что нашел следующую статью, кажется, это очень хорошо объясняет: http://www.codeproject.com/KB/linq/rewrite_linq_expressions2.aspx

1 голос
/ 11 ноября 2010

Что-то, что я схватил из MSDN: идея в том, что вы просто указываете на существующую функцию:

с использованием System;

открытый класс GenericFunc

{
   public static void Main()
   {
      Func<string, string> convertMethod = UppercaseString;
   }

   private static string UppercaseString(string inputString)
   {
      return inputString.ToUpper();
   }
}

Я уверен, что есть и другие способы.Я помню, что делал что-то вроде

new Func<WorkItem, bool>((item => item.projectId == criteria.ProjectId))

Но я не уверен.я уверен, что вам нужно «новое», надеюсь, это поможет:)

...