Анализатор зависимостей дерева выражений

Я создаю анализатор зависимостей дерева выражений для перекрестного источника данных IQueryProvider.

То есть, У меня есть IQueryable с некоторыми элементами, которые могут выполняться локально в памяти против некоторого произвольного поставщика (скажем, Entity Framework). Некоторые другие элементы в IQueryable противоречат сущности, которая мне нужна для удаленного вызова WCF. Операция WCF берет сериализованное дерево выражений, десериализует его, выполняет запрос LINQ для своего собственного локального хранилища данных (скажем также, Entity Framework), а затем отправляет мне обратно результаты (хотя этот механизм может также легко быть службой данных 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();

Запрос - это простая запрашиваемая оболочка с моим собственным провайдером, у которой есть возможность проанализировать дерево и выяснить, что делать перед заменой корней другим провайдером запросов. Итак, в приведенном выше случае мне нужно:

  1. Выполнить запрос к MyEntityA, используя контекст локального объекта, и применить только критерии myEntityX.SomeProperty == "Hello" . То есть запустите локально следующее:

    // предполагаем функциональность для замены нового Query новым
    t explode пытается выполнить мой запрос 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 - это простой запрашиваемая оболочка с моим собственным поставщиком, у которой есть возможность проанализировать дерево и выяснить, что делать, прежде чем заменять корни другим поставщиком запросов. Итак, в приведенном выше случае мне нужно:

    1. Выполнить запрос к MyEntityA, используя контекст локального объекта, и применить только критерии myEntityX.SomeProperty == "Hello" . То есть запустите локально следующее:

      // предполагаем функциональность для замены нового Query новым
      t explode пытается выполнить мой запрос 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 - это простой запрашиваемая оболочка с моим собственным поставщиком, у которой есть возможность проанализировать дерево и выяснить, что делать, прежде чем заменять корни другим поставщиком запросов. Итак, в приведенном выше случае мне нужно:

      1. Выполнить запрос к MyEntityA, используя контекст локального объекта, и применить только критерии myEntityX.SomeProperty == "Hello" . То есть запустите локально следующее:

        // предполагаем функциональность для замены нового Query новым
        - это простая запрашиваемая оболочка с моим собственным поставщиком, у которой есть возможность проанализировать дерево и выяснить, что делать, прежде чем заменять корни другим поставщиком запросов. Итак, в приведенном выше случае мне нужно:

        1. Выполнить запрос к MyEntityA, используя контекст локального объекта, и применить только критерии myEntityX.SomeProperty == "Hello" . То есть запустите локально следующее:

          // предполагаем функциональность для замены нового Query новым
          - это простая запрашиваемая оболочка с моим собственным поставщиком, у которой есть возможность проанализировать дерево и выяснить, что делать, прежде чем заменять корни другим поставщиком запросов. Итак, в приведенном выше случае мне нужно:

          1. Выполнить запрос к MyEntityA, используя контекст локального объекта, и применить только критерии myEntityX.SomeProperty == "Hello" . То есть запустите локально следующее:

            // предполагаем функциональность для замены нового Query новым
            критериев. То есть запустите локально следующее:

            // предполагаем функциональность для замены нового Query новым
            критериев. То есть запустите локально следующее:

            // предполагаем функциональность для замены нового Query новым
            // ObjectContext () уже существует ...
            var resultX = (из entityX в новом запросе ()
            где entityX.SomeProperty == "Hello"). ToList (). AsQueryable ();

          2. Отправить следующую сериализованную версию и запустить ее в моей удаленной службе WCF, а затем вернуть результаты.

            // Отправить предыдущее выражение по сети
            // и возвращаем результаты (поверьте, это уже работает)
            var resultY = (из entityY в новом запросе ()
            где entityY.SomeOtherProperty == "Hello 2"). ToList (). AsQueryable ();

          3. Выполнить в памяти следующее:

            var finalResult = (из entityX в resultX
            от entityY в результатеY
            где entityX.SomeProperty == "Hello" &&
            entityY.SomeOtherProperty == "Привет 2" &&
            entityX.Id == entityY.XId) .ToList ();

          Обратите внимание, что решение должно включать способ накопления критериев, который также указывается вне проекций ... например,

          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 для выполнения операций в памяти с улучшенной производительностью.

          Итак, у меня есть некоторые идеи (например, выполнение нескольких проходов по дереву с посетителем и накопление кандидатов для данный тип сущности), но я ищу предложения других людей о том, как накапливать части моего дерева выражения, которые могут быть выполнены в заданном контексте ... то есть зная, что тот, в котором критерии применяются к одному базовому new Запрос и другой критерий применяется к другому ... чтобы я мог выяснить, что я могу сделать с хранилищем данных 1, что я могу сделать с хранилищем данных 2 и что мне нужно делать в памяти, и выполнить другие части дерева соответственно. Это что-то вроде Funcletizer, но немного сложнее ...

          Спасибо за любую помощь.

6
задан 16 revs 7 October 2010 в 22:43
поделиться