实体框架中灵活的字符串过滤器



我创建了这个方法来准备一个'Func'服务器端,这样我就可以应用一个' flexible"字符串过滤器到我的LINQ查询。但也许我做错了。Func不允许在Where子句中运行。

有什么方法可以解决这个问题,或者我应该做不同的事情吗?我希望该方法可用于我的模型中的多个字符串字段。

这是我在得知行不通之前计划使用的方法。

public static Tuple<Func<string,bool>, bool> PrepareFilterFieldFunc(string filter)
{
bool valid = false;
var retFunc = new Func<string, bool> ((string query_val)=>{
return true;
});
string filter_string = "";
if (filter.Contains("*")) 
{
var f_strs = filter.Split("*");
if (f_strs.Length == 3)   //contains
{
if (f_strs[0] == "" && f_strs[2] == "")
{
filter_string = f_strs[1];
retFunc = new Func<string, bool> ((string query_val)=>{
return query_val.Contains(filter_string);
});
valid = true;
}
else
{
filter_string = filter;
retFunc = new Func<string, bool> ((string query_val)=>{
return query_val.Equals(filter_string);
});
valid = true;
}
}
else if (f_strs.Length == 2)   //startswith or endswith
{
if (f_strs[0] == "")   //startswith
{
filter_string = f_strs[1];
retFunc = new Func<string, bool> ((string query_val)=>{
return query_val.StartsWith(filter_string);
});
valid = true;
}
else if (f_strs[1] == "")  //endswith
{
filter_string = f_strs[1];
retFunc = new Func<string, bool> ((string query_val)=>{
return query_val.EndsWith(filter_string);
});
valid = true;
}
else
{
filter_string = filter;
retFunc = new Func<string, bool> ((string query_val)=>{
return query_val.Equals(filter_string);
});
valid = true;
}
}
else
{
filter_string = filter;
retFunc = new Func<string, bool> ((string query_val)=>{
return query_val.Equals(filter_string);
});
valid = true;
}
}
else
{
filter_string = filter;
retFunc = new Func<string, bool> ((string query_val)=>{
return query_val.Equals(filter_string);
});
valid = true;
}
return new Tuple<Func<string, bool>, bool>( retFunc, valid);
}

在准备查询时,我想运行以下代码:

( Func<string, bool> FuncCountryFilter, bool boolExecuteCountryFilter ) = 
SHARED.PrepareFilterFieldFunc(SHQ.filter_countryCode);
if (boolExecuteCountryFilter)
{
type_query = type_query.Where( sh => FuncCountryFilter( sh.bill_to_country_region_code ) );
}

但是我得到了下面的错误:

未处理的例外。系统。NotSupportedException: LINQ to Entities中不支持LINQ表达式节点类型'Invoke' .

根据评论中的建议,我花了一些时间学习表达式。这可能不是最优雅/最有效的方法。但它似乎有效。

public static IQueryable<Tmodel> WildcardFilter<Tmodel>(string filter_field, string filter_value, IQueryable<Tmodel> previous_query ){

var type = typeof (Tmodel);
var pe = Expression.Parameter(type, "p");
var propertyReference = Expression.Property(pe, filter_field);

string filter_string =  filter_value.Replace("*", string.Empty);
if (filter_value.StartsWith("*") && filter_value.EndsWith("*")){
var constantReference = Expression.Constant(filter_string);
MethodInfo mi = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
Expression filterExpression = Expression.Call(propertyReference, mi, constantReference);
var lambdaComparrison = Expression.Lambda<Func<Tmodel, bool>> ( filterExpression, pe );
return previous_query.Where(lambdaComparrison);
}else if (filter_value.StartsWith("*")){

var constantReference = Expression.Constant(filter_string);
MethodInfo mi = typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
Expression filterExpression = Expression.Call(propertyReference, mi, constantReference);
var lambdaComparrison = Expression.Lambda<Func<Tmodel, bool>> ( filterExpression, pe );
return previous_query.Where(lambdaComparrison);
}else if (filter_value.EndsWith("*")){
var constantReference = Expression.Constant(filter_string);
MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
Expression filterExpression = Expression.Call(propertyReference, mi, constantReference);
var lambdaComparrison = Expression.Lambda<Func<Tmodel, bool>> ( filterExpression, pe );
return previous_query.Where(lambdaComparrison);
}else{
var constantReference = Expression.Constant(filter_value);
var filterExpression = Expression.Equal(propertyReference, constantReference);
var lambdaComparrison = Expression.Lambda<Func<Tmodel, bool>> ( filterExpression, pe );
return previous_query.Where(lambdaComparrison);
}
}

最新更新