建设“平”,而不是“树”LINQ EX pressions [英] Building 'flat' rather than 'tree' LINQ expressions

查看:115
本文介绍了建设“平”,而不是“树”LINQ EX pressions的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用一些code(可<一个href="http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx"相对=nofollow>此处 MSDN上)动态地构建一个包含多个OR'条款'LINQ EX pressions。

I'm using some code (available here on MSDN) to dynamically build LINQ expressions containing multiple OR 'clauses'.

相关code是

var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));

var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));

这会产生一个LINQ EX pression,看起来是这样的:

This generates a LINQ expression that looks something like this:

(((((ID = 5) OR (ID = 4)) OR (ID = 3)) OR (ID = 2)) OR (ID = 1))

我用这个前pression击球时的递归限制(100),所以我想产生一个前pression看起来是这样的:

I'm hitting the recursion limit (100) when using this expression, so I'd like to generate an expression that looks like this:

(ID = 5) OR (ID = 4) OR (ID = 3) OR (ID = 2) OR (ID = 1)

我将如何修改EX pression建设code做到这一点?

How would I modify the expression building code to do this?

推荐答案

您需要修改的产生,因此它建立了 s的序列的营养均衡的树,而不是其中左子树是一个单一的前pression和右子树包含所有剩余的元素。图形:

You need to modify the generation so that it builds a ballanced tree instead of a sequence of ORs where the left sub-tree is a single expression and the right sub-tree contains all remaining elements. Graphically:

 Your code               Better
 ---------              --------
    OR                     OR
 #1    OR              OR      OR
     #2  OR          #1  #2  #3  #4
       #3  #4

正如你可以看到,即使在这个简单的情况下,更好的方法是不一样深深地(递归嵌套)。在code,以产生更好的EX pression树可以写成一个递归方法在C#:<​​/ P>

As you can see, even in this simple case, the better approach is not as deeply (recursively nested). The code to generate the better expression tree can be written as a recursive method in C#:

Expression GenerateTree(List<Expression> exprs, int start, int end) {
  // End of the recursive processing - return single element
  if (start == end) return exprs[start];

  // Split the list between two parts of (roughly the same size)
  var mid = start + (end - start)/2;
  // Process the two parts recursively and join them using OR
  var left = GenerateTree(exprs, start, mid);
  var right = GenerateTree(exprs, mid+1, end);
  return Expression.Or(left, right);
}

// Then call it like this:
var equalsList = equals.ToList();
var body = GenerateTree(equalsList, 0, equalsList.Length);

我没有尝试在code,所以有可能会出现一些小错误,但它应该表现出的主意。

I didn't try the code, so there may be some minor mistakes, but it should show the idea.

这篇关于建设“平”,而不是“树”LINQ EX pressions的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆