首页 > 解决方案 > linq 语句中的项目计数返回 0

问题描述

假设我有以下 EF6 Linq 语句,它计算 2 个表的项目数(表 1 有 10 个项目,表 2 没有项目):

var q = db.Table1.GroupBy(g => "Table1").Select(g => new { Name = g.Key, EntryCount = g.Count() })
          .Union(db.Table2.GroupBy(g => "Table2").Select(g => new { Name = g.Key, EntryCount = g.Count() }));

var r = q.ToList();

预期的结果应该是这样的

Name    | EntryCount
---------------------
Table1  |   10
Table2  |    0

但是,因为 Table2 没有任何项目,所以它没有出现在最终结果中,我得到以下信息:

Name    | EntryCount
---------------------
Table1  |   10

如何确保表 2 始终出现在最终列表中,即使它为空且没有任何记录?

为了让您了解我为什么要执行此 Linq 语句的背景,我将以下 TSQL 语句转换为 linq 查询:

CREATE FUNCTION [dbo].[ufnGetLookups] ()
RETURNS
@lookupsWithItemCounts TABLE 
(
    [Name] VARCHAR(100),
    [EntryCount] INT
)

AS 
BEGIN
    INSERT INTO @lookupsWithItemCounts([Name],[EntryCount])
     VALUES
               ('Table1', (SELECT COUNT(*) FROM Table1)),
               ('Table2', (SELECT COUNT(*) FROM Table2)),
               ('Table3', (SELECT COUNT(*) FROM Table3))

    RETURN;
END

对于此 linq 语句在一次数据库行程中运行,而不是多次运行,这一点也非常重要。

标签: c#entity-frameworklinqlinq-to-sqllinq-to-entities

解决方案


如果您有一个表格列表,那么表格列表可以用于union一行,EntryCount = 0然后在最终结果集GroupBy上使用名称和SumofEntryCount将提供所需的结果。

//List of tables
var tableList = new string[] { "Table1", "Table2" }; 

var res = db.Table1
    .GroupBy(t1 => "Table1")
    .Select(gt1 => new { Name = gt1.Key, EntryCount = gt1.Count()})
    .Union(db.Table2
           .GroupBy(t2 => "Table2")
           .Select(gt2 => new { Name = gt2.Key, EntryCount = gt2.Count()})
          )
    .Union(tableList
           .GroupBy(s => s)
           .Select(gs => new { Name = gs.Key, EntryCount = 0 })
          )
    .GroupBy(gg => gg.Name)
    .Select(fg => new {Name = fg.Key, EntryCount=fg.Select(ee => ee.EntryCount).Sum()})
       .ToList();

结果将具有列表中所有表的 EntryCount。


推荐阅读