我正在用C#开发一个ASP.NET MVC3应用程序。
我正在尝试在我的应用程序中实现“narrow-down”功能应用从搜索获得的结果集。
简而言之,在我执行搜索并将结果显示在页面中心后,我希望在页面的左/右侧为每个属性设置一个CheckBoxList
帮助器< / strong>的搜索结果。每个CheckBox
的{{1}}代表该属性的不同值。
例如,如果我搜索CheckBoxList
并且它的Product
属性值为 blue,red 和 yellow ,我会创建一个{{ 1}}文字颜色和三个Color
- 每种颜色一个。
在网上进行研究后,我发现Scott Guthrie提供了这个动态LINQ 库。由于我发现最近的一个示例/教程是从2009年开始,我想知道这个库是否真的很好(和维护)。
在后一种情况下 jQuery 是实现此类功能的最佳方式吗?
答案 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 。
这取决于您渲染结果的方式。通常,有很多方法可以实现所需的行为:
修改强>
如果我是你(并且需要在服务器端过滤结果),我会做类似的事情:
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。