将TSQL转换为Linq到实体

时间:2015-10-21 09:36:41

标签: c# entity-framework linq tsql linq-to-entities

我有两个名为FileList和ExtensionsCategory的表:

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

1     C:\7.pdf        pdf
2     D:\3.png        png
3     C:\1.mp3        mp3
4     D:\32.pdf       pdf

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

1        mp3           Multimedia
2        pdf           Document
3        png           Photo

表之间没有任何关系。

现在我想知道每个类别包含多少个文件? 我在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);

2 个答案:

答案 0 :(得分:1)

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

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()
                        };
                  });
使用Linq-to-objects

Fiddle

<强>更新

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

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

答案 1 :(得分:1)

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

第一个GroupBy文件扩展名和CountGroupBy元素选择器内的文件扩展名。在那里,您还可以获取这些文件扩展名中的键的类别名称:

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]

Groupped Files

另一方面,@ 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行测试了两个查询,结果是:

Client Statistics - Fast

VS。 ToList版本:

Client Statistic - Slow

在统计信息的最后几行中,您可以看到 short 版本的速度提高了约3倍。