动态LINQ是否仍在使用,适合缩小搜索结果?

时间:2012-04-16 15:17:01

标签: asp.net-mvc-3 linq filtering dynamic-linq

我正在用C#开发一个ASP.NET MVC3应用程序。

我正在尝试在我的应用程序中实现“narrow-down”功能应用从搜索获得的结果集。

简而言之,在我执行搜索并将结果显示在页面中心后,我希望在页面的左/右侧为每个属性设置一个CheckBoxList帮助器< / strong>的搜索结果。每个CheckBox的{​​{1}}代表该属性的不同值

例如,如果我搜索CheckBoxList并且它的Product属性值为 blue,red yellow ,我会创建一个{{ 1}}文字颜色和三个Color - 每种颜色一个。

在网上进行研究后,我发现Scott Guthrie提供了这个动态LINQ 库。由于我发现最近的一个示例/教程是从2009年开始,我想知道这个库是否真的很好(和维护)。

在后一种情况下 jQuery 是实现此类功能的最佳方式吗?

5 个答案:

答案 0 :(得分:5)

您可以使用纯.NET框架动态构建所需的谓词表达式来解决它。

请参阅下面的代码示例。根据条件,这将过滤多个属性。我已经使用了IQuerable,因为这将使In-Memory成为远程场景,例如Entity Framework。如果你要使用Entity Framework,你也可以动态构建一个EntitySQL字符串。我希望这会更好。

涉及一小部分反射(GetProperty)。但是这可以通过在BuildPredicate方法中执行缓存来改进。

public class Item
{
    public string Color { get; set; }
    public int Value { get; set; }
    public string Category { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var list = new List<Item>()
        {
            new Item (){ Category = "Big", Color = "Blue", Value = 5 },
            new Item (){ Category = "Small", Color = "Red", Value = 5 },
            new Item (){ Category = "Big", Color = "Green", Value = 6 },
        };

        var criteria = new Dictionary<string, object>();
        criteria["Category"] = "Big";
        criteria["Value"] = 5;

        var query = DoDynamicWhere(list.AsQueryable(), criteria);
        var result = query.ToList();
    }

    static IQueryable<T> DoDynamicWhere<T>(IQueryable<T> list, Dictionary<string, object> criteria)
    {
        var temp = list;

        //create a predicate for each supplied criterium and filter on it.
        foreach (var key in criteria.Keys)
        {
            temp = temp.Where(BuildPredicate<T>(key, criteria[key]));
        }

        return temp;
    }

    //Create i.<prop> == <value> dynamically
    static Expression<Func<TType, bool>> BuildPredicate<TType>(string property, object value)
    {
        var itemParameter = Expression.Parameter(typeof(TType), "i");

        var expression = Expression.Lambda<Func<TType, bool>>(
            Expression.Equal(
                Expression.MakeMemberAccess(
                    itemParameter,
                    typeof(TType).GetProperty(property)),
                Expression.Constant(value)
            ),
            itemParameter);

        return expression;
    }
}

答案 1 :(得分:2)

我真的不明白为什么你需要 Dynamic LINQ ?项目属性在编译时是否未知?如果您可以按名称访问给定的项目属性,例如。 var prop = myitem['Color'],您不需要动态LINQ

这取决于您渲染结果的方式。通常,有很多方法可以实现所需的行为:

  1. 完全客户端。如果你做所有客户端(获取数据,渲染,分页) - jQuery将是最好的方式。
  2. 服务器端+客户端。如果您在服务器上呈现结果,您可以为每个搜索结果标记添加HTML属性(对于每个属性),并过滤那些客户端即可。在这种情况下唯一的问题可能是分页(如果你做分页服务器端,你将只能过滤当前页面
  3. 完全服务器端。使用搜索参数发布表单并使用LINQ缩小搜索结果 - 将现有项目的属性与表单值匹配。
  4. 修改

    如果我是你(并且需要在服务器端过滤结果),我会做类似的事情:

        var filtered = myItems.Where(i => i.Properties.Match(formValues))
    

    其中Match是一种扩展方法,用于检查给定的属性列表是否与提供的值匹配。这很简单 - 不需要动态LINQ

    编辑2

    您是否需要将LINQ查询映射到数据库查询(LINQ to SQL)?这会使事情变得复杂,但仍然可以通过链接多个.Where(...)子句来实现。只需循环遍历过滤器属性,并将.Where(...)添加到上一次迭代的查询中。

答案 2 :(得分:0)

您可以在Nutshell中查看C#4.0作者的PredicateBuilder

答案 3 :(得分:0)

正如@Piotr Szmyd已经指出的那样,你可能不需要动态的Linq。迭代T的所有属性不需要动态linq。 Dynamic Linq主要用于在客户端构建完整查询并以字符串格式将其发送到服务器。 但是现在它已经过时了,因为Mvc 4通过返回IQueryable的Api控制器支持客户端查询。 如果您只需要迭代T的所有属性,您可以使用反射并构建将构成过滤条件的LambdaExpressions来完成。您可以使用Expression class的静态方法来完成此操作。 通过使用这种静态方法,您可以构建动态表达式,如m =&gt; m.Name =“尼克”,带有几条指示...比你放入它们......完成你得到的表达你可以申请一个exixting IQueryable

答案 4 :(得分:0)

LINQ实现仍未改变,因此使用动态LINQ库应该没有问题。它只是从字符串创建LINQ表达式。

您可以使用AJAX调用运行LINQ查询并返回JSON数据的操作方法。 JQuery将从返回的数据中填充HTML。