分组联接表

时间:2019-05-27 15:23:19

标签: c# entity-framework

我正在尝试连接产品和属性表,并按产品ID对其进行分组,以获取具有其属性的产品列表。因此,我尝试了以下实体框架查询:

    var productsWithAttributes = (from product in ctx.products
                                  join attribute in ctx.attributes on product.id equals attribute.productId
                                  select new
                                     {
                                          product = product,
                                          a1 = attribute.a1,
                                          a2 = attribute.a2,
                                          a3 = attribute.a3,
                                          a4 = attribute.a4
                                  } into t
                                  group t by t.product.id into g
                                     select new
                                     {
                                         product = g.Select(p => p.product).FirstOrDefault(),
                                         attributes = g.Select(r => new Attr()
                                         {
                                             a1 = r.a1,
                                             a2 = r.a2,
                                             a3 = r.a3,
                                             a4 = r.a4
                                         }).ToList()
                                     }
                                    ).ToList();

但这花了大约70分钟,当我查看它产生的SQL查询时,我看到了数十个带有数十个联接的子查询。

然后,我尝试仅在sql服务器上进行分组,然后将投影投影到应用程序服务器上所需的结构中。这是该代码的EF代码:

    var productsWithAttributes = (from product in ctx.products
                                  join attribute in ctx.attributes on product.id equals attribute.productId
                                  select new
                                      {
                                          product = product,
                                          a1 = attribute.a1,
                                          a2 = attribute.a2,
                                          a3 = attribute.a3,
                                          a4 = attribute.a4
                                  } into t
                                      group t by t.product.id

                            ).ToList();

这花了大约3分钟。但是,此查询产生的SQL看起来仍然很复杂,包含多个子查询和联接。我会遵循以下原则:

select product.*, attribute.a1, attribute.a2, attribute.a3, attribute.a4
from product
join attribute on product.id = attribute.productId
group by product.id

然后我只尝试了联接而没有分组:

    var productsWithAttributes = (from product in ctx.products
                                      join attribute in ctx.attributes on product.id equals attribute.productId
                                      select new
                                      {
                                          product = product,
                                          a1 = attribute.a1,
                                          a2 = attribute.a2,
                                          a3 = attribute.a3,
                                          a4 = attribute.a4,

                                      }
                                    ).ToList();

这花了1.5分钟,EF产生的SQL代码符合预期。

简而言之,将分组添加到联接中会创建一个复杂的SQL查询,该查询花费更长的时间,但从性能上来说还是可以接受的。但是,在此分组之后添加最终投影会产生难以理解的卷积SQL查询,该查询耗时且无法理解。

使用EF创建此查询的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

如果要创建联接表,那么您要做的就是用pk(Primay键)创建另一个表并完全联接它们,而不是内部联接它们或只联接联接。

答案 1 :(得分:1)

在LINQ to Entities中创建此类查询的推荐方法是使用集合导航属性,或者在缺少它的情况下-Group Join构造(<div class="container"> <page-profile :user="{{ $user->toJson() }}"></page-profile> </div> ):

  

一个组联接产生一个分层的结果序列,该结果序列将左侧源序列中的元素与右侧源序列中的一个或多个匹配元素相关联。团体联接在关系方面没有等效项;它本质上是一个对象数组序列。

类似这样的东西:

join ... into