C#泛型LINQ查询 [英] C# Generic Linq Query
问题描述
我需要写一些像这样的通用搜索方式:
I need to write some generic Search Method like this:
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
对象。
,此功能将成为所有不同班。例如:
and I have a function CreateQuery()
that should filter IEnumerable
object.
This function will be different for all classes. For example:
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;
}
我怎样才能正确地实现这个想法?
How can I implement this idea correctly?
推荐答案
你想要做这里bascically动态构建LINQ查询什么。要做到这一点,你需要修改/在运行时构建表达式树。如果你不熟悉表达式树和表达式来; T>
键入我推荐这篇文章和另请参阅一节中引用的网页:
What you want to do here is bascically constructing a LINQ query dynamically. To do this, you need to modify/build the expression tree at runtime. If you are not familiar with expression trees and the Expression<T>
type I recommend this article and the referenced pages in the "See also" section:
http://msdn.microsoft.com/ EN-US /库/ bb397951.aspx
现在,你现在的基本概念,让我们实现动态排序。下面的方法是一个扩展到的IQueryable< T>
这意味着它不仅适用于名单,但每一个LINQ数据源,所以你也可以直接使用它针对数据库(这是更有效的,当涉及到寻呼和比内存操作排序)。该方法需要你想订购属性名称和排序方向(升序/降序):
Now that you now the basic concept, let's implement dynamic sorting. The method below is an extension to IQueryable<T>
which means it does not only apply to lists but to every LINQ datasource, so you could also use it directly against a database (which is more efficient when it comes to paging and sorting than in memory operations). The method takes the property name you want to order by and the sort direction (ascending/descending):
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);
}
现在,你可以这样写代码,命令由物业数据集名称
在升
命令:
Now you can write this code to order the dataset by the property Name
in ascending
order:
dataSet.OrderByDynamic("Name", false)
创建动态过滤的扩展方法如下相同的模式。如果你理解了上面的代码,它不会成为你的问题。
Creating an extension methods for dynamic filtering follows the same pattern. If you understand the code above, it won't be a problem for you.
这篇关于C#泛型LINQ查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!