Если вы хотите получить отфильтрованные данные, вы можете создать Expression самостоятельно. Я делаю некоторые примеры для вашей задачи, но вам нужно улучшить их для вашего источника или создать некоторые глобальные улучшения
давайте начнем с конца. Я не могу заставить Expression возвращать анонимный тип, поэтому я создаю общий, который планирую использовать как результат
public class GRes<T>
{
public T Key { get; set; }
public int Count { get; set; }
}
Я собираюсь выполнить группировку по любому полю объекта или самого объекта, а затем по результатам этой группировки вызовем Sum fnction с некоторой лямбдой, которая выглядит следующим образом
x=>0 + IIF(x.Code.Contains(p1), 1, 0) + IIF(x.Code.Contains(p2), 1, 0) ...
где Код - это какое-то поле, а p1, p2 ... - ваши условия поиска
на последнем звонке будет
IQueriable<GRes<Book>> result = context.Books
.GroupBy(d => d).CountIn(searchTerms, "Code")
.Where(r => r.Count > 0)
.OrderByDescending(r => r.Count);
CountIn - это расширение:
public static IQueryable<GRes<TKey>> CountIn<TKey, TValue>(this IQueryable<IGrouping<TKey, TValue>> source, IEnumerable<string> values, Expression<Func<TValue,string>> selector)
{
ParameterExpression xExpr = selector.Parameters[0];
Expression propExpr = selector.Body;
MethodInfo mi = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
Expression res = Expression.Constant(0);
foreach (string term in values)
{
Expression value = Expression.Constant(term);
MethodCallExpression methodEpr = Expression.Call(propExpr, mi,value);
Expression tx = Expression.Condition(methodEpr, Expression.Constant(1), Expression.Constant(0));
res = Expression.Add(res, tx);
}
var r0 = Expression.Lambda<Func<pp_Disease, int>>(res, xExpr);
Type groupingType = typeof(IGrouping<TKey, TValue>);
ParameterExpression selPar = Expression.Parameter(groupingType, "i");
MethodInfo mi1 = typeof(Enumerable).GetMethods()
.FirstOrDefault(m => m.Name == "Sum"
&& m.ReturnParameter.ParameterType == typeof(int)
&& m.GetParameters().Count() == 2)
.MakeGenericMethod(typeof(pp_Disease));
Expression r1 = Expression.MemberInit(Expression.New(typeof(GRes<TKey>))
, Expression.Bind(typeof(GRes<TKey>).GetMember("Count")[0], Expression.Call(mi1, selPar, r0))
, Expression.Bind(typeof(GRes<TKey>).GetMember("Key")[0], Expression.Property(selPar, "Key")));
return source.Select(Expression.Lambda<Func<IGrouping<TKey, TValue>, GRes<TKey>>>(r1, selPar));
}
и когда эта функция будет вызвана, вы получите SQL следующим образом:
SELECT
...
FROM ( SELECT
...
FROM ( SELECT
....
SUM([Extent1].[A1]) AS [A1]
FROM ( SELECT
...
0 + (CASE WHEN ([Extent1].[Code] LIKE N'%2%') THEN 1 ELSE 0 END) + (CASE WHEN ([Extent1].[Code] LIKE N'%I%') THEN 1 ELSE 0 END) AS [A1]
FROM (SELECT
...
FROM [dbo].[pp_Disease] AS [pp_Disease]) AS [Extent1]
) AS [Extent1]
GROUP BY [K1], [K2], [K3], [K4]
) AS [GroupBy1]
WHERE [GroupBy1].[A1] > 0
) AS [Project1]
ORDER BY [Project1].[C1] DESC
я удалил некоторые объявления полей (EF сгенерировал sql огромный), наиболее важным для этого примера является строка с параметрами, которые мы поместили в нашу функцию