首页 > 解决方案 > Linq Count() 将始终在 Visual Studio 中返回 1

问题描述

背景

现在我有一个名为 FoorBar 的系统,其中有用户、房间和授权。

详细背景

一个用户可以拥有多个授权,并且可以将多个房间添加到单个授权中。为了处理这个问题,我有以下表格:FooBar_UserFooBar_UserAuthFooBar_AuthorizationFoorBar_AuthTypeFooBar_RoomAuthRoom_Inventory

我需要一个查询来返回授权 id、用户拥有的房间数、授权类型和授权的到期日期。

SQL

生成所需输出的 ​​SQL 如下:

SELECT a.AuthId
    ,COUNT(ra.RoomAuthId) AS RmCnt
    ,fat.AuthTypeAbbr
    ,a.ExpirationDate

FROM FooBar_User AS u
    INNER JOIN FooBar_UserAuth AS ua ON u.UserId = ua.UserId
    INNER JOIN FooBar_Authorization AS a ON ua.AuthId = a.AuthId
    INNER JOIN FooBar_AuthType AS fat ON a.AuthTypeId = fat.AuthTypeId
    LEFT JOIN FooBar_RoomAuth AS ra ON a.AuthId = ra.AuthId AND ra.IsActive = 1
    LEFT JOIN Room_Inventory AS ri ON ra.RmId = ri.RMID AND ri.IsActive = 1

WHERE   a.IsActive =  1
    AND u.IsActive =  1
    AND u.UserId   = 10

GROUP BY a.AuthId, fat.AuthTypeAbbr, a.ExpirationDate

LINQ 查询

from ua in db.FooBar_UserAuth
join ra in db.FooBar_RoomAuth
    on new { ua.FooBar_Authorization.AuthId, IsActive = true }
    equals new { ra.AuthId, ra.IsActive } into raJoin
from ra in raJoin.DefaultIfEmpty()
join ri in db.Room_Inventory
    on new { ra.RmId, IsActive = true }
    equals new { RmId = ri.RMID, ri.IsActive } into riJoin
from ri in riJoin.DefaultIfEmpty()
where
    ua.FooBar_Authorization.IsActive &&
    ua.IsPi == true &&
    ua.FooBar_User.IsActive &&
    ua.FooBar_User.UserId == 10
group new { ua.FooBar_Authorization, ua.FooBar_Authorization.FooBar_AuthType, ra } by new
{
    AuthId = (int?)ua.FooBar_Authorization.AuthId,
    ua.FooBar_Authorization.FooBar_AuthType.AuthTypeAbbr,
    ua.FooBar_Authorization.ExpirationDate
} into g
select new
{
    AuthId = g.Key.AuthId.Value,
    RmCnt = g.Count(p => p.ra.RoomAuthId != 0),
    AuthType = g.Key.AuthTypeAbbr,
    ExpirationDate = g.Key.ExpirationDate
}

LINQPad 和 Linqer 输出

AuthId  RmCnt   AuthType    ExpirationDate
30      0       Type1       12/31/2020
31      0       Type2       12/31/2020

问题

问题是这个 LINQ 查询在 Linqer 和 LINQPad 中运行时都能完美运行。输出完全符合要求。但是,当它在带有 ASP.NET、MVC 和实体框架的 C# 中运行时,RmCnt 永远不会是0. 相反,它将是1. 无论发生什么变化,似乎都是如此。另一位用户提出了类似的问题,但我不知道如何将他们的解决方案应用于我的查询。

任何帮助,将不胜感激。

标签: c#sqlsql-serverasp.net-mvclinq

解决方案


我解决了这个问题

问题

我仍然不确定问题的根本原因是什么,因为我最初在 LINQPad 和 Linqer 中完美运行的 LINQ 查询,但在实际代码中却没有。

但是,我从 Linqer 的原始输出中更改的一件事是更改p.ra.AuthTypeId != null为,p.ra.AuthTypeId != 0因为 Visual Studio 抱怨AuthTypeId永远不能为空,因为它是一个int而不是一个Nullable<int>.

解决方案

这实际上是一个相当简单的改变。p.ra.AuthTypeId != 0需要更改为p.ra != null. 此解决方案使 Visual Studio 不会抱怨可空类型,但仍保持相同的输出。

完整的工作 LINQ 查询

from ua in db.FooBar_UserAuth
join ra in db.FooBar_RoomAuth
    on new { ua.FooBar_Authorization.AuthId, IsActive = true }
    equals new { ra.AuthId, ra.IsActive } into raJoin
from ra in raJoin.DefaultIfEmpty()
join ri in db.Room_Inventory
    on new { ra.RmId, IsActive = true }
    equals new { RmId = ri.RMID, ri.IsActive } into riJoin
from ri in riJoin.DefaultIfEmpty()
where
    ua.FooBar_Authorization.IsActive &&
    ua.IsPi == true &&
    ua.FooBar_User.IsActive &&
    ua.FooBar_User.UserId == 10
group new { ua.FooBar_Authorization, ua.FooBar_Authorization.FooBar_AuthType, ra } by new
{
    AuthId = (int?)ua.FooBar_Authorization.AuthId,
    ua.FooBar_Authorization.FooBar_AuthType.AuthTypeAbbr,
    ua.FooBar_Authorization.ExpirationDate
} into g
select new
{
    AuthId = g.Key.AuthId.Value,
    RmCnt = g.Count(p => p.ra != null),
    AuthType = g.Key.AuthTypeAbbr,
    ExpirationDate = g.Key.ExpirationDate
}

推荐阅读