我怎样才能使 Sum() return 0 而不是 'null'?
How can I make Sum() return 0 instead of 'null'?
我正在尝试使用 LINQ-to-entities 查询我的数据库,其中我有 3 个表:Room
、Conference
和 Participant
。每个房间都有很多会议,每个会议有很多参与者。对于每个房间,我试图计算其会议的数量,以及该房间所有会议的所有参与者的总和。这是我的查询:
var roomsData = context.Rooms
.GroupJoin(
context.Conferences
.GroupJoin(
context.Participants,
conf => conf.Id,
part => part.ConferenceId,
(conf, parts) => new { Conference = conf, ParticipantCount = parts.Count() }
),
rm => rm.Id,
data => data.Conference.RoomId,
(rm, confData) => new {
Room = rm,
ConferenceCount = confData.Count(),
ParticipantCount = confData.Sum(cd => cd.ParticipantCount)
}
);
当我尝试将其转换为列表时,出现错误:
The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
我可以通过将 Sum
行更改为:
来解决此问题
ParticipantCount = confData.Count() == 0 ? 0 : confData.Sum(cd => cd.ParticipantCount)
但麻烦的是,这似乎生成了一个更复杂的查询,并增加了 100 毫秒的查询时间。有没有更好的方法让我告诉 EF 在对 ParticipantCount
求和时,confData
的空列表应该只表示零,而不是抛出异常?烦人的是这个错误只发生在 EF 上;如果我创建一个空的 in-memory List<int>
并对其调用 Sum()
,它会返回零,而不是抛出异常!
使用Enumerable.DefaultIfEmpty
:
ParticipantCount = confData.DefaultIfEmpty().Sum(cd => cd.ParticipantCount)
您可以使用 null coalescing operator ??如:
confData.Sum(cd => cd.ParticipantCount ?? 0)
我通过将 Sum
行更改为:
使其工作
ParticipantCount = (int?)confData.Sum(cd => cd.ParticipantCount)
令人困惑的是,即使 IntelliSense 告诉我正在使用 Sum()
的 int
重载,但在运行时它实际上正在使用 int?
重载,因为 confData
列表可能为空。如果我明确地告诉它 return 类型是 int?
它 returns null
用于空列表条目,我稍后可以空合并 null
s归零。
与其尝试让 EF 生成 returns 0 而不是 null 的 SQL 查询,不如像这样在客户端处理查询结果时更改它:
var results = from r in roomsData.AsEnumerable()
select new
{
r.Room,
r.ConferenceCount,
ParticipantCount = r.ParticipantCount ?? 0
};
AsEnumerable()
强制对 SQL 查询求值,后续查询运算符是客户端 LINQ-to-Objects。
我正在尝试使用 LINQ-to-entities 查询我的数据库,其中我有 3 个表:Room
、Conference
和 Participant
。每个房间都有很多会议,每个会议有很多参与者。对于每个房间,我试图计算其会议的数量,以及该房间所有会议的所有参与者的总和。这是我的查询:
var roomsData = context.Rooms
.GroupJoin(
context.Conferences
.GroupJoin(
context.Participants,
conf => conf.Id,
part => part.ConferenceId,
(conf, parts) => new { Conference = conf, ParticipantCount = parts.Count() }
),
rm => rm.Id,
data => data.Conference.RoomId,
(rm, confData) => new {
Room = rm,
ConferenceCount = confData.Count(),
ParticipantCount = confData.Sum(cd => cd.ParticipantCount)
}
);
当我尝试将其转换为列表时,出现错误:
The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
我可以通过将 Sum
行更改为:
ParticipantCount = confData.Count() == 0 ? 0 : confData.Sum(cd => cd.ParticipantCount)
但麻烦的是,这似乎生成了一个更复杂的查询,并增加了 100 毫秒的查询时间。有没有更好的方法让我告诉 EF 在对 ParticipantCount
求和时,confData
的空列表应该只表示零,而不是抛出异常?烦人的是这个错误只发生在 EF 上;如果我创建一个空的 in-memory List<int>
并对其调用 Sum()
,它会返回零,而不是抛出异常!
使用Enumerable.DefaultIfEmpty
:
ParticipantCount = confData.DefaultIfEmpty().Sum(cd => cd.ParticipantCount)
您可以使用 null coalescing operator ??如:
confData.Sum(cd => cd.ParticipantCount ?? 0)
我通过将 Sum
行更改为:
ParticipantCount = (int?)confData.Sum(cd => cd.ParticipantCount)
令人困惑的是,即使 IntelliSense 告诉我正在使用 Sum()
的 int
重载,但在运行时它实际上正在使用 int?
重载,因为 confData
列表可能为空。如果我明确地告诉它 return 类型是 int?
它 returns null
用于空列表条目,我稍后可以空合并 null
s归零。
与其尝试让 EF 生成 returns 0 而不是 null 的 SQL 查询,不如像这样在客户端处理查询结果时更改它:
var results = from r in roomsData.AsEnumerable()
select new
{
r.Room,
r.ConferenceCount,
ParticipantCount = r.ParticipantCount ?? 0
};
AsEnumerable()
强制对 SQL 查询求值,后续查询运算符是客户端 LINQ-to-Objects。