有没有办法在linq查询中参数化方法?

在我使用Linq to SQL的应用程序中,用户可以搜索文本。 可以在搜索表达式的开头和/或结尾使用星号(*)。 代码现在是这样的:

var search = SearchTextBox.Text.Trim(); bool filterStartsWith = false, filterEndsWith = false; if (!string.IsNullOrEmpty(search)) { filterStartsWith = search.EndsWith("*"); filterEndsWith = search.StartsWith("*"); if (filterStartsWith) search = search.Substring(0, search.Length - 1); if (filterEndsWith) search = search.Substring(1); if (filterStartsWith) { if (filterEndsWith) { query = query.Where(item => item.Omschrijving.Contains(search)); } else { query = query.Where(item => item.Omschrijving.StartsWith(search)); } } else { if (filterEndsWith) { query = query.Where(item => item.Omschrijving.EndsWith(search)); } else { query = query.Where(item => item.Omschrijving == search); } } } 

但是,我想概括一下,因为这种搜索发生在更多的地方。 此外,一些表,这应该发生在多个列上。 有任何想法吗?

我将Visual Studio 2010与.NET Framework 4.0一起使用。

你可以试试这个:

 static IQueryable WhereColumnContains(this IQueryable source, Expression> selector, string search) { if (string.IsNullOrWhiteSpace(search)) { return source; } Expression> expression; search = search.Trim(); var filterStartsWith = search.EndsWith("*"); var filterEndsWith = search.StartsWith("*"); if (filterEndsWith) search = search.Substring(1); if (filterStartsWith) { search = search.Substring(0, search.Length - 1); if (filterEndsWith) { var parameter = Expression.Parameter(typeof(T), "parameter"); expression = Expression.Lambda>( Expression.Call(Expression.Invoke(selector, parameter), typeof(string).GetMethod("Contains", new[] { typeof(string) }), Expression.Constant(search)), parameter); } else { var parameter = Expression.Parameter(typeof(T), "parameter"); expression = Expression.Lambda>( Expression.Call(Expression.Invoke(selector, parameter), typeof(string).GetMethod("StartsWith", new[] { typeof(string) }), Expression.Constant(search)), parameter); } } else { if (filterEndsWith) { var parameter = Expression.Parameter(typeof(T), "parameter"); expression = Expression.Lambda>( Expression.Call(Expression.Invoke(selector, parameter), typeof(string).GetMethod("EndsWith", new[] { typeof(string) }), Expression.Constant(search)), parameter); } else { var parameter = Expression.Parameter(typeof(T), "parameter"); expression = Expression.Lambda>( Expression.Equal(Expression.Invoke(selector, parameter), Expression.Constant(search)), parameter); } } return source.Where(expression); } 

称其如下:

 query = query.WhereColumnContains(item => item.Omschrijving, search); 

您可以使用策略模式。 你将有4个策略基于“搜索”值和“bool CanHandle(搜索)”方法,工厂创建策略列表,你的程序将调用一个客户端,只需创建一个新工厂,调用方法“BuildQuery(搜索)”执行使用CanHandle方法找到的正确策略,并返回查询值。

http://en.wikipedia.org/wiki/Strategy_pattern

您可以使用动态构建的表达式。

下面是在多列上实现StartWith的示例代码(可能无法编译,我直接在stackoverflow中键入它) – 只需添加对其他方法的支持…

此代码适用于所有linq-to-sql查询,假设“columnsToSearch”始终引用字符串属性。

 IQueryable myQuery = ... your query you want to filter ...; string searchWhat = "text to search"; bool startsWith; Expression condition = null; var p = Expression.Parameter(myQuery.ElementType,"x"); foreach (string column in columnsToSearch) { if (startsWith) { var myCondition = Expression.Call(Expression.PropertyOrField(p, column), typeof (string).GetMethod("StartsWith"), Expression.Constant(searchWhat)); if (condition == null) condition = myCondition; else condition = Expression.OrElse(condition, myCondition); } } var newQuery = Expression.Call(typeof (Queryable).GetMethod("Where"), myQuery.Expression, Expression.Lambda(condition, p)); var myQueryFiltered = myQuery.Provider.CreateQuery(newQuery); 

简而言之,如果你有一个查询myRepository.Where(t=>t.Mycondition)这段代码将生成一个新的查询,如myRepository.Where(t=>t.Mycondition).Where(t=>t.Field1.StartsWith("a")||t.Field2.StartWith("a")) (取决于你给它的列当然)

然后,你所要做的就是将“myQueryFiltered”强制转换为IEnumerable或IQueryable,以便执行get过滤结果:)