Linq选择在内存中执行的非重复计数

时间:2018-08-17 09:42:04

标签: c# linq entity-framework-core

我正在努力了解LINQ如何转换为SQL。

我要使用LINQ生成以下查询。

SELECT [OrganizationId]
  ,[DepartmentId]
  ,[LocationName]
  ,[Group1]
  ,[Group2]
  ,[Group3]
  ,[BooklistId]
  ,[BooklistName]
  ,COUNT(DISTINCT [OrdererId])
  ,MAX([ExpectedDate])
FROM [Orders]
WHERE ([DepartmentId] IS NOT NULL AND ([DepartmentId] = '<Guid>')) AND ([Schoolyear] = '2018')
GROUP BY [OrganizationId]
  ,[DepartmentId]
  ,[LocationName]
  ,[Group1]
  ,[Group2]
  ,[Group3]
  ,[BooklistId]
  ,[BooklistName]
ORDER BY [BooklistName]

使用索引,此查询将在200毫秒内执行。

我的LINQ查询如下:

await _context
            .Orders
            .Where(i => i.DepartmentId != null && i.DepartmentId.Equals(Parameters.DepartmentId))
            .Where(i => i.SchoolYear.Equals(Parameters.SchoolYear))
            // Group the data.
            .GroupBy(orders => new
            {
                orders.BooklistId,
                orders.BooklistName,
                orders.OrganizationId,
                orders.DepartmentId,
                orders.LocationName,
                orders.Groep1,
                orders.Groep2,
                orders.Groep3
            })
            .OrderBy(i => i.Key.BooklistName)
            .Select(i => new BookListViewModel
            {
                Count = i.Select(orders => orders.OrdererId).Distinct().Count(s => s != null),
                Id = i.Key.OrganizationId,
                Name = i.Key.BooklistName,
                LocationName = i.Key.LocationName,
                Number = i.Key.BooklistId,
                Group1 = i.Key.Group1,
                Group2 = i.Key.Group2,
                Group3 = i.Key.Group3,
                DepartmentId = i.Key.DepartmentId,
                ExpectedDate = i.Max(orders => orders.ExpectedDate)
            })
            .ToListAsync();

但是我一直看到:

  

Microsoft.EntityFrameworkCore.Query:警告:LINQ表达式'GroupBy(new <> f__AnonymousType1`8(BooklistId = [i] .BooklistId,BooklistName = [i] .BooklistName,OrganizationId = [i] .OrganizationId,DepartmentId = [i] .DepartmentId,LocationName = [i] .LocationName,Group1 = [i] .Group1,Group2 = [i] .Group2,Group3 = [i] .Group3),[i])'无法翻译,将在本地进行评估。

     

Microsoft.EntityFrameworkCore.Query:警告:LINQ表达式'Distinct()'无法翻译,将在本地进行评估。

     

Microsoft.EntityFrameworkCore.Query:警告:LINQ表达式'where([s]!= null)'无法翻译,将在本地进行评估。

     

Microsoft.EntityFrameworkCore.Query:警告:LINQ表达式'Count()'无法翻译,将在本地进行评估。

谁能告诉我为什么LINQ查询在内存中执行?我需要在LINQ查询中进行哪些更改才能获得所需的结果?

1 个答案:

答案 0 :(得分:1)

查询正在内存中执行,因为您使用语句实例化了BookListViewModel对象的集合

.Select(i => new BookListViewModel
            {...})

如果仅删除类BookListViewModel,Linq将在db端执行执行查询(这是个好主意,因为优化器效率更高)...

.Select(i => new
            {
                Count = i.Select(orders => orders.OrdererId).Distinct().Count(s => s != null),
                i.Key.OrganizationId,
                i.Key.BooklistName,
                i.Key.LocationName,
                i.Key.BooklistId,
                i.Key.Group1,
                i.Key.Group2,
                i.Key.Group3,
                i.Key.DepartmentId,
                ExpectedDate = i.Max(orders => orders.ExpectedDate)
            })

然后,您可以在最后实例化您的集合,以便使整个过程看起来像这样……

await _context
            .Orders
            .Where(i => i.DepartmentId != null && i.DepartmentId.Equals(Parameters.DepartmentId))
            .Where(i => i.SchoolYear.Equals(Parameters.SchoolYear))
            // Group the data.
            .GroupBy(orders => new
            {
                orders.BooklistId,
                orders.BooklistName,
                orders.OrganizationId,
                orders.DepartmentId,
                orders.LocationName,
                orders.Group1,
                orders.Group2,
                orders.Group3
            })
            .OrderBy(i => i.Key.BooklistName)
.Select(i => new
            {
                Count = i.Select(orders => orders.OrdererId).Distinct().Count(s => s != null),
                i.Key.OrganizationId,
                i.Key.BooklistName,
                i.Key.LocationName,
                i.Key.BooklistId,
                i.Key.Group1,
                i.Key.Group2,
                i.Key.Group3,
                i.Key.DepartmentId,
                ExpectedDate = i.Max(orders => orders.ExpectedDate)
            })
            .Select(i => new BookListViewModel
            {
                Count = i.Count,
                Id = i.Id,
                Name = i.Name,
                LocationName = i.LocationName,
                Number = i.Number ,
                Group1 = i.Group1 ,
                Group2 = i.Group2,
                Group3 = i.Group3,
                DepartmentId = i.DepartmentId,
                ExpectedDate = i.ExpectedDate
            })
            .ToListAsync();