将 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 倍。
我有 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 倍。