and*_*ndy 2 linq foreach lambda expression-trees
好的家伙,和我一起裸露.我先总结一下,然后再详细说明.
我编写了许多方法(.WhereOr,.WhereAnd),基本上允许我"堆叠"一堆lambda查询,然后将它们应用到集合中.例如,数据集的用法有点像这样(虽然它可以通过使用泛型与任何类一起使用):
使用LINQ TO DATASETS(使用.NET DataSetExtensions)
DataTable Result;
List<Expression<Func<DataRow, bool>> Queries = new List<Expression<Func<DataRow, bool>>();
Queries.Add(dr=> dr.Field<string>("field1") == "somestring");
Queries.Add(dr=> dr.Field<string>("field2") == "somestring");
Queries.Add(dr=> dr.Field<string>("field3") == "somestring");
Result = GetSomeTable().AsEnumarable().WhereOr(Queries).CopyToDataTable();
Run Code Online (Sandbox Code Playgroud)
现在说在上面的例子中,集合中只有一行匹配"somestring",而它位于字段"field2"上.
这意味着Result的计数应为1.
现在,假设我稍微重写上面的代码:
DataTable Result;
List<Expression<Func<DataRow, bool>> Queries = new List<Expression<Func<DataRow, bool>>();
List<string> columns = new string[]{"field1","field2","field3"}.ToList();
string col;
foreach(string c in columns){
col = c;
Queries.Add(dr=> dr.Field<string>(col) == "somestring");
}
Result = GetSomeTable().AsEnumarable().WhereOr(Queries).CopyToDataTable();
Run Code Online (Sandbox Code Playgroud)
现在,我并不真正理解表达,但对我来说,上面的两个例子都做了完全相同的事情.
除了第一个示例中的"Result"的计数为1,而第二个示例中的"Result"的计数为0.
此外,在第二个示例的List列中,如果将"field2"设置为last,而不是second,则"Result"的计数正确为1.
所以,从这一切来看,我得出了一个结论,但我真的不明白发生了什么,也不知道如何解决它......?我可以更早地"评估"那些表达式......还是其中的一部分?
结论:
基本上,似乎,如果我将文字值发送到那里,比如"field1",它就可以了.但是如果我发送变量,比如"col",它就不起作用,因为这些"表达式"只会在代码中稍后进行评估.
这也可以解释为什么当我将"field2"移动到最后位置时它才起作用.它的工作原理是因为变量"col"最后被分配给"field2",因此当表达式评估"col"等于"field2"时.
好的,那么,有什么方法可以解决这个问题吗?
这是我的WhereOr方法的代码(它是IENumerable的扩展方法):
public static IQueryable<T> WhereOr<T>(this IEnumerable<T> Source, List<Expression<Func<T, bool>>> Predicates) {
Expression<Func<T, bool>> FinalQuery;
FinalQuery = e => false;
foreach (Expression<Func<T, bool>> Predicate in Predicates) {
FinalQuery = FinalQuery.Or(Predicate);
}
return Source.AsQueryable<T>().Where(FinalQuery);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> Source, Expression<Func<T, bool>> Predicate) {
InvocationExpression invokedExpression = Expression.Invoke(Predicate, Source.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.Or(Source.Body, invokedExpression), Source.Parameters);
}
Run Code Online (Sandbox Code Playgroud)
我甚至不再费心阅读问题机构,我只是读了标题,然后说
看到
http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!689.entry
和
"如何修复"答案.改变这个:
string col;
foreach(string c in columns) {
col = c;
Queries.Add(dr=> dr.Field<string>(col) == "somestring");
}
Run Code Online (Sandbox Code Playgroud)
对此:
foreach(string c in columns) {
string col = c;
Queries.Add(dr=> dr.Field<string>(col) == "somestring");
}
Run Code Online (Sandbox Code Playgroud)
请享用.Brian给出了"什么和为什么"的答案.