由於您的代碼示例中的表達式很長,可能很難看到,但它顯示「Where」子句包含錯誤,因爲它不是可以簡化爲Func<T, bool>
的表達式。
我假設這就是爲什麼你得到一個編譯器錯誤。沒有關於KendoFilterDescription
是什麼的更多信息,ParsePropertyValue
所做的以及您想要使用PatIndex
過濾的內容,很難爲您提供一個很好的答案。
所以現在我會盡量胡亂猜測:
- 您嘗試使用PATINDEX表達式過濾的IQueryable。
- 如果評估的PatIndex表達式不返回0,則「Where」應計算爲true,因此該記錄包含在結果中。
- 您希望PatIndex表達式的參數
stringPattern
等於ParsePropertyValue(filter)
的返回值,即要匹配的模式。
- 您希望PatIndex表達式的
target
參數等於名稱爲filter.Field
的屬性或字段T
的值。
所以作爲一個例子,我們來看一個具有屬性FirstName和LastName的類Person(T)。再假設您要在姓的含有一定文字過濾,然後你想建立一個像一個表達式:
Func<string, string> BuildContainsPattern = phrase => string.Format("%{0}%", phrase);
Func<IQueryable<Person>, string, IQueryable<Person>> whereFirstNameContains =
(data, phrase) => data.Where(p => SqlFunctions.PatIndex(BuildContainsPattern(phrase), p.FirstName) > 0);
假設這是(基本上)是正確的。我們需要一些構建模塊,這些模塊一起允許我們構建可以傳遞到IQueryable<T>
的Where
子句的Expression<Func<T, bool>>
。
好吧,那麼困難的部分首先。下面的BuildFilterExpression
函數可以爲我們構建這個表達式,只要我們提供(1)作爲PatIndex
函數的第一個參數預期的stringPattern
和(2)我們希望的實體類型T
的屬性名稱用作PatIndex
函數的第二個參數。
因此,如果我對ParsePropertyValue(filter)
和filter.Field
表示的假設是正確的,則下面的代碼應使用過濾器提供的設置進行過濾。
using System;
using System.Linq;
using System.Reflection;
using System.Data.Objects.SqlClient;
using System.Linq.Expressions;
public class FilterDescription
{
public enum FilterPatternType
{
Contains = 1,
Range = 2, // [^0-9]
}
public string Field { get; set; }
public string FilterPhrase { get; set; }
public FilterPatternType PatternType { get; set; }
}
public static class FilterBuilder
{
private static readonly MethodInfo PatIndexMethod = typeof(SqlFunctions).GetMethod("PatIndex");
private static readonly ConstantExpression ValueZero = Expression.Constant(0, typeof(int?));
public static string ParsePropertyValue(FilterDescription filter)
{
switch (filter.PatternType)
{
case FilterDescription.FilterPatternType.Contains:
return string.Format("%{0}%", filter.FilterPhrase);
case FilterDescription.FilterPatternType.Range:
return string.Format("[^{0}]", filter.FilterPhrase);
default:
throw new InvalidOperationException("Pattern type not supported");
}
}
public static Expression<Func<TEntity, bool>> BuildFilterExpression<TEntity>(string patternString, string targetProperty)
{
var patternStringArg = Expression.Constant(patternString);
var entityType = Expression.Parameter(typeof(TEntity), "item");
var targetPropertyArg = Expression.PropertyOrField(entityType, targetProperty);
MethodCallExpression patIndexCall = Expression.Call(PatIndexMethod, patternStringArg, targetPropertyArg);
var isGreaterThanZero = Expression.GreaterThan(patIndexCall, ValueZero);
return Expression.Lambda<Func<TEntity, bool>>(isGreaterThanZero, entityType);
}
public static Expression<Func<TEntity, bool>> BuildFilterExpression<TEntity>(FilterDescription filter)
{
var pattern = ParsePropertyValue(filter);
return BuildFilterExpression<TEntity>(pattern, filter.Field);
}
public static IQueryable<TEntity> Filter<TEntity>(this IQueryable<TEntity> toFilter, FilterDescription filter)
{
return toFilter.Where(BuildFilterExpression<TEntity>(filter));
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
class Program
{
private static IQueryable<Person> GetPersons()
{
return (IQueryable<Person>)null; // use your own data.
}
public static void Main(params string[] args)
{
var filter = new FilterDescription()
{
PatternType = FilterDescription.FilterPatternType.Contains,
Field = "FirstName",
FilterPhrase = "ed"
};
var filtered = GetPersons().Filter(filter);
}
}
顯然,這是可能的,我完全得到了我的胡亂猜測錯了,但我想你會提高你的你想達到什麼樣的描述。
您可以精心設計您想要完成的任務嗎?沒有爲你工作:'(filteredData,filter)=> filteredData.Where(f => System.Data.Objects.SqlClient.SqlFunctions.PatIndex(「@ 0」,「」)!= 0);' – eestein
@Mediator:當問一個問題時,特別是如果問題沒有明確說明時,如果您至少可以迴應那些努力爲您提供答案並要求澄清的人員關於你想要達到的目標。你能否請你這樣做。 – Alex