Могу ли я использовать скомпилированный запрос в качестве источника во втором запросе? - PullRequest
4 голосов
/ 09 апреля 2011

У меня есть скомпилированный запрос, который отлично работает. Я передаю ему product_id, и он возвращает информацию о товаре для этого продукта.

Можно ли использовать этот скомпилированный запрос в качестве источника для подзапроса? Пример:

from cat in ctx.cat_table 
join prod in ctx.prod_table on cat.category_id equals prod.category_id
select new
{
    cat_id = cat.category_id,
    prod_id = prod.product_id,
    name = prod.product_name,
    descript = prod.product_description,
    price = prod.price,
    reviews = (from mcq in mycompiledquery(ctx, prod.product_id)
               select new 
               {
                   rating = mcq.review_rating,
                   review = mcq.review_text
               }    
}

Мои ранние попытки сделать что-то подобное вызывают ошибку:

Тип узла выражения LINQ 'Invoke' не поддерживается в LINQ to Entities

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

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

Ответы [ 2 ]

2 голосов
/ 10 апреля 2011

Вы можете использовать скомпилированный запрос в другом запросе, но вы не можете сделать его зависимым от внешнего запроса.Примеры

// You can do 
var someParams = 10;
var dataQuery = from x in ctx.SomeData
                join y in myCompiledQuery.Invoke(ctx, someParams) 
                    on x.Id equals y.Id
                where x.Name = "ABC"
                select new { x, y };

// You can't do - this example will not compile but let's use it for description
var dataQuery = from x in ctx.SomeData
                join y in myCompiledQuery.Invoke(ctx, x.SomeParams) 
                    on x.Id equals y.Id
                where x.Name = "ABC"
                select new { x, y };

Разница в том, что первый пример просто выполняет делегат (скомпилированный запрос является делегатом) и возвращает IQueryable.Второй пример не может выполнить делегат, потому что он зависит от внешних данных запроса, поэтому он принимает его как нечто, что должно быть добавлено в дерево выражений и элюировано во время выполнения запроса.Это не удается, поскольку поставщик EF не может перевести вызов делегата.

0 голосов
/ 09 апреля 2011

Вы можете комбинировать и встраивать запросы, но я не думаю, что вы можете использовать скомпилированные запросы. Это действительно не должно иметь большого значения, потому что EF скомпилирует комбинированный запрос только один раз, а затем кеширует его (и серверная часть базы данных должна кешировать соответствующий план запроса).

Поэтому вы можете использовать что-то вроде этого:

var reviewQuery = from mcq in reviews
                  select new 
                  {
                      prod_id = mcq.prod_id
                      rating = mcq.review_rating,
                      review = mcq.review_text
                  };

 from cat in ctx.cat_table 
 join prod in ctx.prod_table on cat.category_id equals prod.category_id
 select new
 {
      cat_id = cat.category_id,
      prod_id = prod.product_id,
      name = prod.product_name,
      descript = prod.product_description,
      price = prod.price,
      reviews = from r in reviewQuery where r.prod_id == prod_id select r
 }
...