我需要像这样编写一些通用的搜索方法:
public List<T> Search<T>(SearchParamsBase searchParams)
{
using (var context = new TestEntities())
{
var dataType = TypeMap.Get(typeof (T));
var dataSet = context.Set(dataType);
var searchQuery = CreateQuery((IEnumerable<object>) dataSet), searchParams)
return searchQuery.ToList()
}
}
我有一个函数 CreateQuery()
应该过滤 IEnumerable
对象。
这个函数对于所有类都是不同的。例如:
CreateQuery(IEnumerable<object> collection, SearchParamsBase searchParams)
{
var search = (SomeSearchImplementation)searchParams;
// filter
collection = collection.Where(x => x.Name == search.Name);
// select page
collection = collection.Skip(search.Page * search.CountPerPage);
collection = collection.Take(search.CountPerPage);
// order by and so on
// ...
return collection;
}
我怎样才能正确地实现这个想法?
最佳答案
您在这里基本上想要做的是动态构建 LINQ 查询。为此,您需要在运行时修改/构建表达式树。如果您不熟悉表达式树和 Expression<T>
我在“另请参阅”部分中推荐这篇文章和引用页面:
http://msdn.microsoft.com/en-us/library/bb397951.aspx
现在您已经了解了基本概念,让我们来实现动态排序。下面的方法是对 IQueryable<T>
的扩展这意味着它不仅适用于列表,而且适用于每个 LINQ 数据源,因此您还可以直接对数据库使用它(这在分页和排序方面比在内存操作中更有效)。该方法采用您要排序的属性名称和排序方向(升序/降序):
public static IQueryable<T> OrderByDynamic<T>(this IQueryable<T> query, string sortColumn, bool descending)
{
// Dynamically creates a call like this: query.OrderBy(p => p.SortColumn)
var parameter = Expression.Parameter(typeof(T), "p");
string command = "OrderBy";
if (descending)
{
command = "OrderByDescending";
}
Expression resultExpression = null;
var property = typeof(T).GetProperty(sortColumn);
// this is the part p.SortColumn
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
// this is the part p => p.SortColumn
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
// finally, call the "OrderBy" / "OrderByDescending" method with the order by lamba expression
resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { typeof(T), property.PropertyType },
query.Expression, Expression.Quote(orderByExpression));
return query.Provider.CreateQuery<T>(resultExpression);
}
现在您可以编写此代码以按属性 Name
对数据集进行排序在 ascending
顺序:
dataSet.OrderByDynamic("Name", false)
为动态过滤创建扩展方法遵循相同的模式。如果您理解上面的代码,这对您来说不是问题。
关于C# 通用 Linq 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15925091/