代码之家  ›  专栏  ›  技术社区  ›  Sander Rijken

使用Expression.Subtract(?)对子查询进行算术运算

  •  1
  • Sander Rijken  · 技术社区  · 14 年前

    我正在尝试创建一个表达式树,它类似于执行子查询,例如:

    SELECT (SELECT Sum(Foo) FROM Bar1) - (SELECT Sum(Foo) FROM Bar2))
    

    我正在尝试重用两个过于复杂而无法重复的表达式树。

    Expression<Func<Bar, int>> SumBar1 =
        (bar) => (from b in bar.Something
                  where b.Type = 1
                  select b).Sum();
    
    Expression<Func<Bar, int>> SumBar2 =
        (bar) => (from b in bar.Something
                  where b.Type = 2
                  select b).Sum();
    

    我已经试过用 Expression.Subtract :

    Expression foo = Expression.Subtract(SumBar1, SumBar2);
    

    此操作失败,错误为:

    为类型定义 '系统.Func 2[Bar,System.Int32]' and 'System.Func 2[Bar,System.Int32]'。

    Expression.Invoke 叫树:

    Expression.Invoke(SumBar1,Expression.Parameter(typeof(Bar)), Expression.Invoke(SumBar2,Expression.Constant(typeof(Bar)));

    但后来我发现:

    LINQ表达式节点类型“Invoke” 在LINQ to实体中不支持。

    有没有办法将这两个表达式树组合成一个新树,减去它们,然后传递参数?

    2 回复  |  直到 14 年前
        1
  •  2
  •   Chris Pitman    14 年前

    当动态地为EF构建Linq查询时,会出现很多这样的情况,而您几乎就做到了。我以前写过手工操作的代码,但是使用 LinqKit

    使用LinqKit之后,只需编写一个lambda表达式,该表达式调用两个子表达式并减去结果。然后对结果表达式调用“Expand”并保存结果。新表达式将不再处理调用,因为传递给内部表达式的参数已被替换到它们的主体中,并且方法调用已被移除。

    Expression<Func<Bar, int>> SumBar1 = 
        (bar) => (from b in bar.Something 
                  where b.Type = 1 
                  select b).Sum(); 
    
    Expression<Func<Bar, int>> SumBar2 = 
        (bar) => (from b in bar.Something 
                  where b.Type = 2 
                  select b).Sum();
    
    Expression<Func<Bar, int>> Combined = (bar) => SumBar1.Invoke(bar) - SumBar2.Invoke(bar);
    Expression<Func<Bar, int>> Result = Combined.Expand();
    
        2
  •  0
  •   Onkelborg    14 年前

    现在我不知道英孚,但林肯,这听起来有点奇怪。为什么要从另一个代理中减去一个代理?

    Expression<Func<Bar, int>> sumBar1 =
        (bar) => (from b in bar.Something
                  where b.Type = 1
                  select b).Sum();
    
    Expression<Func<Bar, int>> sumBar2 =
        (bar) => (from b in bar.Something
                  where b.Type = 2
                  select b).Sum();
    
    Expression<Func<Bar, int>> totalSum =
        bar =>
                  sumBar1(bar) - sumBar2(bar);
    
    totalSum(DB.GetBar());
    

    不过,我得预约,我还没有真正测试过这个,这可能是完全错误的。。:)