我正在构建一个动态查询,该查询可以具有n个Where方法调用和n个SelectMany调用,具体取决于用户输入。例如,我可能有:



var qZ = entityContext.TableA
        .SelectMany(a=>a.TableB, (a,t)=>new{a,t}  )
        .Where(a=>a.t.FieldID==21)
        .Where(a=> EntityFunctions.Left(a.t.Value,1)=="p")
        .SelectMany(a=>a.a.TableC, (a,t)=>new{a,t}  )
        .Where(a=>a.t.FieldID==22)
        .Where(a=> a.a.t.Value=="Peter" && a.t.Value=="Pan")
        .Where(a=> a.a.a.TypeID==3)
        .Select(a=> new{ a.a.a.ItemID }
        ).Distinct();


在我编写的方法中,我使用了辅助方法,这些方法返回IQueryable,如下面的返回行所示。

return query.Provider.CreateQuery(
    Expression.Call(typeof(Queryable),
      "Where",
       new Type[] {query.ElementType},
       query.Expression, predicateLambda)
           );


我可以为所需的所有各种查询属性-值对创建LambdaExpressions,但无法为resultSelectorQueryable.SelectMany创建一个。

我们如何在表达式树中创建(a,t) => new{a=a, t=t}?或者我们如何像下面那样使用Expression.Call完成与上面.SelectMany相同的结果?

Expression.Call(typeof(Queryable),
      "SelectMany",
       ????????,
       ????????
           );


我试过使用SelectMany重载,该重载在某种程度上不需要resultSelector,但是,我不知道如何在后续方法调用中引用t的属性。

我已经在整个Web上找到了与(a,t) => new{a=a, t=t}相关联的lambda表达式(SelectMany),但是我找不到如何将其转换为表达式树的任何示例。

更新:
让我们重新构想这个问题。我可以这样通过lambda

var q = entityContext.TableA.AsQueryable();

var q1 = Queryable.SelectMany(q, a => a.TableB, (a, t) => new { a = a, t = t });

var q2 = Queryable.Where(q1,a=>a.t.FieldID==22);


但是,这行得通,因为我不提前知道需要调用多少个SelectMany,并且由于每个调用都更改为IQueriable的匿名类型,因此有一种方法可以将匿名类型强制转换(并重新广播)为单变量?这样,我可以循环遍历并将所需的任何方法应用于变量,然后在查询建立后枚举以获取结果。就像是:

var q = entityContext.TableA..AsQueryable();

q = Queryable.SelectMany(q, a => a.TableB, (a, t) => new { a = a, t = t });

q = Queryable.Where(q,a=>a.t.FieldID==22);


(顺便说一句:这不起作用)

最佳答案

我最终解决此问题的方式需要进行范式转换。上面的第一个查询是基于以下事实:我学会了通过将所需的所有表连接在一起来编写查询,以便我可以过滤和选择这些表中的字段。

SelectMany()创建联接,并且当时我的想法周围的框要求,如果我需要过滤表中的特定列,则必须将该表联接到查询中。反过来,这改变了IQueryable的类型,导致我无法在设计时预测IQueryable的类型。

回答:

步骤1:将IQueryable的类型设置为需要返回的输出类型。在上述情况下,结果始终为IQueryable。

步骤2:利用表达式动态创建WHERE谓词,包括创建适当过滤器所需的所有表。这总是返回Expression>以及我们容易解释的所有其他变量。记住,在EF中,如果仅在Where()中需要使用表,则不必在Where()之外加入表。

08-04 11:08