将 TSQL 转换为 Linq 到实体

Convert TSQL to Linq to Entities

我有 2 个 table 名为 FileList 和 ExtensionsCategory :

FileList
-------------------------------------------------------------
ID    Path         Extension

1     C:.pdf        pdf
2     D:.png        png
3     C:.mp3        mp3
4     D:.pdf       pdf

ExtensionsCategory 
------------------------------------------------------------
ID     Extension       Category

1        mp3           Multimedia
2        pdf           Document
3        png           Photo

table之间没有任何关系。

现在我想知道每个类别包含多少个文件? 我在 SSMS 中编写了以下 TSQL 查询并且工作正常:

SELECT 
     Category
    ,SUM(FileCount) AS TotalFileCount 
FROM    
    (SELECT 
         COUNT(*) AS FileCount
        ,(SELECT ExtensionsCategories.Category FROM ExtensionsCategories WHERE FileList.Extension = ExtensionsCategories.Extension) AS Category
    FROM FileList GROUP BY Extension) AS T1 GROUP BY Category

我想知道在没有连接的情况下是否有任何改进的方法?

我尝试使用 Linq to Entities 编写它,这是我的代码,但我无法完成它:

    var a = _dbContext.FileLists
        .Select(fl => new
        {
            Extension = fl.Extension,
            Count = _dbContext.FileLists.Count(),
            Cat =
                _dbContext.ExtensionsCategories.Where(w => w.Extension == fl.Extension).Select(s => s.Category)
        }).GroupBy(g => g.Extension);

这应该会给你正确的结果:-

var result = from f in _dbContext.FileLists
             group f by f.Extension into g
             let firstCategory = _dbContext.ExtensionsCategories
                                           .FirstOrDefault(x => x.Extension == g.Key)
             select new
                    {
                        Category = firstCategory != null ? firstCategory.Category : "",
                        TotalFileCount = g.Count()
                    };

或者如果您需要 Method Syntax:-

var result = _dbContext.FileLists.GroupBy(e => e.Extension)
              .Select(x =>
                  {
                      var firstCategory = _dbContext.ExtensionsCategories
                                           .FirstOrDefault(z => z.Extension == x.Key);
                      return new
                        {
                           Category = firstCategory != null ? firstCategory.Category : "",
                           TotalFileCount = x.Count()
                        };
                  });

Fiddle 使用 Linq-to-objects。

更新:

如果一个类别可以包含多个扩展名,那么您可以使用以下查询:-

var result = extensionCat.GroupBy(x => x.Category)
                      .Select(x =>
                         new
                          {
                              Category = x.Key,
                              TotalFileCount = fileList.Count(f => x
                                                    .Any(z => z.Extension == f.Extension))
                          }
                      );

还有另一种方法可以更快地获得相同的结果。

第一个 GroupBy 文件扩展名和 Count 它们在 GroupBy 元素选择器中。在那里您还可以获得键的类别名称,在本例中是文件扩展名:

var result =
    Files
    .GroupBy(x => x.Extension, (ext, fs) => new 
    { 
        Extension = ext, 
        Category = Categories.Single(c => c.Extension == ext).Name, 
        FileCount = fs.Count() 
    });

这将产生以下查询:

SELECT [t1].[Extension], (
    SELECT [t2].[Name]
    FROM [Category] AS [t2]
    WHERE [t2].[Extension] = [t1].[Extension]
    ) AS [Category], [t1].[value] AS [FileCount]
FROM (
    SELECT COUNT(*) AS [value], [t0].[Extension]
    FROM [File] AS [t0]
    GROUP BY [t0].[Extension]
    ) AS [t1]

@RahulSingh 版本另一方面产生了这个:

-- Region Parameters
DECLARE @p0 NVarChar(1000) = ''
-- EndRegion
SELECT 
    (CASE 
        WHEN EXISTS(
            SELECT TOP (1) NULL AS [EMPTY]
            FROM [Category] AS [t2]
            WHERE [t2].[Extension] = [t1].[Extension]
            ) THEN (
            SELECT [t4].[Name]
            FROM (
                SELECT TOP (1) [t3].[Name]
                FROM [Category] AS [t3]
                WHERE [t3].[Extension] = [t1].[Extension]
                ) AS [t4]
            )
        ELSE CONVERT(NVarChar(50),@p0)
     END) AS [Category], (
    SELECT COUNT(*)
    FROM [File] AS [t5]
    WHERE (([t1].[Extension] IS NULL) AND ([t5].[Extension] IS NULL)) OR (([t1].[Extension] IS NOT NULL) AND ([t5].[Extension] IS NOT NULL) AND ([t1].[Extension] = [t5].[Extension]))
    ) AS [TotalFileCount]
FROM (
    SELECT [t0].[Extension]
    FROM [File] AS [t0]
    GROUP BY [t0].[Extension]
    ) AS [t1]

我用 1.000.000 行测试了这两个查询,结果是:

对比ToList 版本:

在统计数据的最后几行中,您可以看到 版本大约快 3 倍。