2

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

我试图在我的应用程序中实现一个“缩小”功能,应用从搜索中获得的结果集。

简而言之,在我执行搜索并将结果显示在页面中心之后,我希望在页面的左侧/右侧为搜索结果CheckBoxList的每个属性提供一个帮助器。每个代表属性的CheckBox不同CheckBoxList

例如,如果我搜索Product并且它有一个Color值为blue、redyellow的属性,我创建一个CheckBoxList带有文本Color和三个CheckBox-es 的每个颜色。

在对 Web 进行研究之后,我发现了这个由 Scott Guthrie 提供的Dynamic LINQ库。由于我发现的最新示例/教程是 2009 年的,我想知道这个库是否真的很好(并且维护)。

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

4

5 回答 5

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;
    }
}
于 2012-05-18T06:49:49.463 回答
2

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

这取决于您如何呈现结果。一般来说,有很多方法可以实现所需的行为:

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

编辑

如果我是你(并且需要在服务器端过滤结果),我会这样做:

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

whereMatch是一个扩展方法,用于检查给定的属性列表是否与提供的值匹配。就这么简单——不需要动态 LINQ

编辑 2

是否需要将 LINQ 查询映射到数据库查询(LINQ to SQL)?这会使事情变得有点复杂,但通过链接多个.Where(...)子句仍然是可行的。只需循环过滤器属性并添加.Where(...)到先前迭代的查询中。

于 2012-04-16T15:42:44.300 回答
0

you may have a look at PredicateBuilder from the author of C# 4.0 in a Nutshell

于 2012-05-15T07:25:07.760 回答
0

正如@Piotr Szmyd 已经指出的那样,您可能不需要动态Linq。遍历 T 的所有属性不需要动态 linq。Dynamic Linq 主要用于在客户端构建完整的查询并将其以字符串格式发送到服务器。但是现在,它已经过时了,因为 Mvc 4 通过返回 IQueryable 的 Api 控制器支持客户端查询。如果您只需要遍历 T 的所有属性,您可以通过反射和构建将构成过滤标准的 LambdaExpressions 来完成。您可以使用Expression 类的静态方法来完成. 通过使用这样的静态方法,您可以使用一些指令构建动态表达式,例如 m => m.Name= "Nick" ...比您输入的和它们...完成后,您可以将表达式应用于现有的 IQueryable

于 2012-05-17T21:51:12.883 回答
0

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

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

于 2012-05-18T22:48:43.187 回答