C#通用Linq查询

6

我需要编写一些通用的搜索方法,就像这样:

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;
}

我该如何正确实现这个想法?
1个回答

9
你需要做的基本上是动态构建一个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升序的方式来排序数据集:

dataSet.OrderByDynamic("Name", false)

创建一个用于动态过滤的扩展方法遵循相同的模式。如果您理解上述代码,那么这将不会成为问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接