为简单起见,我假设我有以下两个类:
public class ComplexClass
{
public List<SubClass> SubClasses { get; set; }
public string Name { get; set; }
}
public class SubClass
{
public string Name { get; set; }
}
我有List<ComplexClass>
,我需要根据一些参数构建查询。
如果我需要做的就是使用Name
的{{1}}属性,这是一项简单的任务。这是一个例子:
ComplexClass
根据我的参数,我可以添加更多的查询元素。当然上面的例子很简单,但实际问题包含更多参数,而且这个数字可以增长。
如果我想找到那些 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;
}
个实例符合参数的ComplexClass
个实例,那么事情并不那么简单:
SubClass
我不能再根据每个参数添加查询位,我现在需要一次编写整个查询,这意味着我需要检查每个参数组合,这几乎不理想。
我怀疑关键是要构建一个 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;
}
类并从中创建一个lambda表达式,但我不确定如何解决这个问题。
有什么建议吗? :)
编辑:
我最初的想法是:
Expression
这适用于我的小型控制台测试应用程序,因为它使用LINQ to Objects。不幸的是,我需要使用Entity Framework和LINQ to Entities,这会导致类似于上面的实现抛出 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;
}
错误消息。
答案 0 :(得分:1)
我假设现实代码中的SubClasses
属性为IQueryable<SubClass>
而不是List<SubClass>
?
如果是这样,那么您的查询构建变得简单:
static IQueryable<ComplexClass> GetSubQuery(
string someParameter, string someOtherParameter)
{
var query = list.AsQueryable();
if (!String.IsNullOrEmpty(someParameter))
query = query.Where(c => c.SubClasses
.Where(sc => sc.Name.StartsWith(someParameter)).Any());
if (!String.IsNullOrEmpty(someOtherParameter))
query = query.Where(c => c.SubClasses
.Where(sc => sc.Name.StartsWith(someOtherParameter)).Any());
return query;
}
使用IEnumerable<T>
混合IQueryable<T>
和AsQueryable()
绝不是一个好主意。
答案 1 :(得分:0)
我在一个简单的控制台项目中实现了我的解决方案:
internal class Program
{
#region Constants and Fields
private static readonly List<ComplexClass> list = new List<ComplexClass>
{
new ComplexClass
{
Name = "complex",
SubClasses = new List<SubClass>
{
new SubClass
{
SubName = "foobar"
}
}
},
new ComplexClass
{
Name = "complex",
SubClasses = new List<SubClass>
{
new SubClass
{
SubName = "notfoobar"
}
}
}
};
#endregion
#region Public Methods
public static void Main(string[] args)
{
Console.WriteLine("foo / bar :");
GetSubQuery("foo", "bar");
Console.WriteLine();
Console.WriteLine("foo / null :");
GetSubQuery("foo", null);
Console.WriteLine();
Console.WriteLine("string.Empty / bar :");
GetSubQuery(string.Empty, "bar");
Console.WriteLine();
Console.WriteLine("maeh / bar :");
GetSubQuery("maeh", "bar");
Console.ReadKey();
}
#endregion
#region Methods
private static void GetSubQuery(string startsWith,
string endsWith)
{
var query = from item in list
let StartIsNull = string.IsNullOrEmpty(startsWith)
let EndIsNull = string.IsNullOrEmpty(endsWith)
where
(StartIsNull || item.SubClasses.Any(sc => sc.SubName.StartsWith(startsWith)))
&& (EndIsNull || item.SubClasses.Any(sc => sc.SubName.EndsWith(endsWith)))
select item;
foreach (var complexClass in query)
{
Console.WriteLine(complexClass.SubClasses.First().SubName);
}
}
#endregion
public class ComplexClass
{
#region Public Properties
public string Name { get; set; }
public List<SubClass> SubClasses { get; set; }
#endregion
}
public class SubClass
{
#region Public Properties
public string SubName { get; set; }
#endregion
}
}
控制台输出为:
foo / bar :
foobar
foo / null :
foobar
string.Empty / bar :
foobar
notfoobar
maeh / bar :