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

时间:2010-10-19 21:36:02

标签: c# linq entity-framework c#-4.0 linq-to-entities

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

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

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

我现在拥有的是2(简化)表达式树:

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);

失败并显示错误:

  

二进制运算符Subtract不是   为类型定义   'System.Func 2[Bar,System.Int32]' and 'System.Func 2 [酒吧,System.Int32]'。

我也尝试使用Expression.Invoke来调用树:

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

但后来我得到了:

  

LINQ表达式节点类型'Invoke'   LINQ to Entities不支持。

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

2 个答案:

答案 0 :(得分:2)

在为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();

答案 1 :(得分:0)

现在我不知道EF,但LINQ,这对我来说听起来有点奇怪。你为什么要从另一个代表中减去一个委托?

更合适的是:

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());

我必须预订,我还没有真正测试过,这可能完全错了.. :)