表达式树依赖性分析器

时间:2010-09-26 06:25:18

标签: c# linq lambda expression-trees

我正在为交叉数据源IQueryProvider构建表达式树依赖关系分析器。

也就是说,我有一个IQueryable,其中包含一些可以在内存中针对某个任意提供程序(比如Entity Framework)执行的元素。 IQueryable中的一些其他元素违反了我需要进行远程WCF调用的实体。 WCF操作采用序列化表达式树,对其进行反序列化,对自己的本地数据存储执行LINQ查询(也就是说实体框架),然后将结果发回给我(尽管这种机制可以很容易地成为WCF数据服务) DataServiceQuery ......但我没有使用它,因为它的功能支持水平是有限的...充其量)。一旦我从WCF服务返回结果,我将针对本地执行的LINQ查询在内存中执行LINQ查询的结果。

那么,那有什么难的呢?好吧,我需要确定表达式树的依赖关系,以便我的本地底层查询提供程序不会爆炸尝试执行我的LINQ查询,该查询具有只能在远程WCF服务上执行的组件......反之亦然。

我们采取简单的方案:

  var result = 
   (from entityX in new Query<MyEntityX>()
   from entityY in new Query<MyEntityY>()
   where entityX.SomeProperty == "Hello" &&
   entityY.SomeOtherProperty == "Hello 2" && entityX.Id == entityY.XId).ToList();

Query<T>是一个简单的可查询包装器,它有我自己的提供程序,它有机会解析树,找出在使用不同的查询提供程序交换根之前要做什么。因此,在上述情况下,我需要:

  1. 使用本地对象上下文对MyEntityA执行查询,并仅应用myEntityX.SomeProperty == "Hello"条件。也就是说,在本地运行以下命令:

    // assume the functionality for replacing new Query<MyEntityA> with new
    // ObjectContext<MyEntityA>() is already there...
    var resultX = (from entityX in new Query<MyEntityX>()
    where entityX.SomeProperty == "Hello").ToList().AsQueryable();

  2. 发送以下序列化文件并在远程WCF服务上执行,然后返回结果。

    // Send the preceeding expression over the over the wire
    // and get the results back (just take my word this already works)
    var resultY = (from entityY in new Query<MyEntityY>()
    where entityY.SomeOtherProperty == "Hello 2").ToList().AsQueryable();

  3. 在内存中执行以下操作:

    var finalResult = (from entityX in resultX
    from entityY in resultY
    where entityX.SomeProperty == "Hello" &&
    entityY.SomeOtherProperty == "Hello 2" &&
    entityX.Id == entityY.XId).ToList();

  4. 请注意,解决方案必须包含一种累积标准的方法,这些标准也是从投影中指定的......比如

    var result = 
    (from i in  
      (from entityX in new Query<MyEntityX>()  
       from entityY in new Query<MyEntityY>()  
       select new { PropX = entityX, PropY = entityY })  
    where  
       i.PropX.SomeProperty == "Hello" && i.PropY.SomeOtherProperty == "Hello 2"  
       && i.PropX.Id == i.PropY.XId  
    select i)  
    .ToList();
    

    这应该导致在内存中评估其余查询之前实际发出相同的两个单独查询。在一个不相关的说明中,我想我可能会使用PLINQ和/或DRYAD来运行内存操作并提高性能。

    所以,我有一些想法(比如用访问者对树进行一些传递,并为给定的实体类型积累候选者),但我正在寻找其他人关于如何积累我的表达式树的部分的建议可以针对给定的上下文执行...也就是说,知道标准适用于一个基础新Query<T>而另一个标准适用于另一个标准...这样我就能弄清楚我能做什么针对数据存储1,我可以对数据存储2做什么以及我需要在内存中做什么,并相应地执行树的不同部分。它有点像Funcletizer,但有点复杂......

    感谢您的帮助。

1 个答案:

答案 0 :(得分:4)