可以在第二个查询中使用已编译的查询作为源吗?

本文关键字:查询 编译 第二个 | 更新日期: 2023-09-27 17:49:24

我有一个编译好的查询,工作得很好。我将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 to Entities中不支持LINQ表达式节点类型'Invoke'

我考虑过的另一种选择是用SQL视图替换我编译的查询,但我担心会对性能产生负面影响。

非常感谢您提供的任何建议

可以在第二个查询中使用已编译的查询作为源吗?

您可以在其他查询中使用编译查询,但不能使其依赖于外部查询。示例

// 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提供程序无法翻译委托调用。

您可以组合和嵌入查询,但我不认为您可以使用编译查询。这真的不应该太重要,因为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
 }