【发布时间】:2012-10-23 10:13:36
【问题描述】:
为简单起见,假设我有以下两个类:
public class ComplexClass
{
public List<SubClass> SubClasses { get; set; }
public string Name { get; set; }
}
public class SubClass
{
public string Name { get; set; }
}
我有一个List<ComplexClass>,我需要根据一些参数构建一个查询。
如果我需要做的只是使用ComplexClass 的Name 属性,这将是一项简单的任务。这是一个例子:
static IQueryable<ComplexClass> GetQuery(string someParameter, string someOtherParameter)
{
var query = list.AsQueryable();
if (!String.IsNullOrEmpty(someParameter))
query = query.Where(c => c.Name.StartsWith(someParameter));
if (!String.IsNullOrEmpty(someOtherParameter))
query = query.Where(c => c.Name.EndsWith(someOtherParameter));
return query;
}
根据我拥有的参数,我可以添加更多查询元素。当然上面的例子很简单,但是实际的问题包含更多的参数,而且这个数量可以增长。
如果我想找到那些具有SubClass 实例且符合基于参数的条件的ComplexClass 实例,事情就没有那么简单了:
static IQueryable<ComplexClass> GetSubQuery(string someParameter, string someOtherParameter)
{
var query = list.AsQueryable();
if (!String.IsNullOrEmpty(someParameter))
if (!String.IsNullOrEmpty(someOtherParameter))
return query.Where(c => c.SubClasses.Where(sc => sc.Name.StartsWith(someParameter) && sc.Name.EndsWith(someOtherParameter)).Any());
else
return query.Where(c => c.SubClasses.Where(sc => sc.Name.StartsWith(someParameter)).Any());
else
if (!String.IsNullOrEmpty(someOtherParameter))
return query.Where(c => c.SubClasses.Where(sc => sc.Name.EndsWith(someOtherParameter)).Any());
else
return null;
}
我不能再根据每个参数添加查询的位,我现在需要一次编写整个查询,这意味着我需要检查每个参数组合,这并不理想。
我怀疑关键是构建一个Expression 类并从中创建一个 lambda 表达式,但我不确定如何解决这个问题。
有什么建议吗? :)
编辑:
我最初的想法是这样的:
static IQueryable<ComplexClass> GetSubQuery(string someParameter, string someOtherParameter)
{
var query = list.AsQueryable();
query = query.Where(c =>
{
var subQuery = c.SubClasses.AsQueryable();
if (!String.IsNullOrEmpty(someParameter))
subQuery = subQuery.Where(sc => sc.Name.StartsWith(someParameter));
if (!String.IsNullOrEmpty(someOtherParameter))
subQuery = subQuery.Where(sc => sc.Name.EndsWith(someOtherParameter));
return subQuery.Any();
});
return query;
}
这适用于我的小型控制台测试应用程序,因为它使用 LINQ to Objects。不幸的是,我需要使用 Entity Framework 和 LINQ to Entities,这会导致类似于上面的实现抛出 A lambda expression with a statement body cannot be converted to an expression tree 错误消息。
【问题讨论】:
-
您使用“someParameter”和“someOtherParameter”只是为了检查它们是否为空,实际上并未在where条件下使用,那么它们的作用是什么?看起来它们与大小写有关。 ..解释更多...
-
您可以将
.Where(predicate).Any()替换为.Any(predicate)。 -
Amol:参数可以为空,是的,但在实际的最终代码中用于查询。事实上,这些例子可能看起来有点傻。我将编辑示例。丹尼尔:我知道,但这不仅仅是问题。