[英]How can I make Sum() return 0 instead of 'null'?
I'm trying to use LINQ-to-entities to query my DB, where I have 3 tables: Room
, Conference
, and Participant
. 我正在尝试使用LINQ-to-entities查询我的数据库,其中有3个表:
Room
, Conference
和Participant
。 Each room has many conferences, and each conference has many participants. 每个房间都有很多会议,每个会议都有很多参与者。 For each room, I'm trying to get a count of its conferences, and a sum of all of the participants for all of the room's conferences.
对于每个房间,我正在尝试统计其会议数量,以及该房间所有会议的所有参与者的总和。 Here's my query:
这是我的查询:
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)
}
);
When I try and turn this into a list, I get the error: 当我尝试将其转换为列表时,出现错误:
The cast to value type 'System.Int32' failed because the materialized value is null.
强制转换为值类型'System.Int32',因为实例化值为null。 Either the result type's generic parameter or the query must use a nullable type.
结果类型的通用参数或查询必须使用可为空的类型。
I can fix this by changing the Sum
line to: 我可以通过将“
Sum
行更改为:
ParticipantCount = confData.Count() == 0 ? 0 : confData.Sum(cd => cd.ParticipantCount)
But the trouble is that this seems to generate a more complex query and add 100ms onto the query time. 但麻烦的是,这似乎会生成更复杂的查询,并使查询时间增加100毫秒。 Is there a better way for me to tell EF that when it is summing
ParticipantCount
, an empty list for confData
should just mean zero, rather than throwing an exception? 有什么更好的办法告诉我EF,在对
ParticipantCount
求和时, confData
的空列表应该只是零,而不是抛出异常? The annoying thing is that this error only happens with EF; 令人讨厌的是,此错误仅在EF中发生; if I create an empty in-memory
List<int>
and call Sum()
on that, it gives me zero, rather than throwing an exception! 如果我创建一个空的内存
List<int>
并对其调用Sum()
,它将给我零,而不是引发异常!
使用Enumerable.DefaultIfEmpty
:
ParticipantCount = confData.DefaultIfEmpty().Sum(cd => cd.ParticipantCount)
You may use the null coalescing operator ?? 您可以使用null合并运算符 ?? as:
如:
confData.Sum(cd => cd.ParticipantCount ?? 0)
I made it work by changing the Sum
line to: 我通过将
Sum
行更改为:
ParticipantCount = (int?)confData.Sum(cd => cd.ParticipantCount)
Confusingly, it seems that even though IntelliSense tells me that the int
overload for Sum()
is getting used, at runtime it is actually using the int?
令人困惑的是,即使IntelliSense告诉我正在使用
Sum()
的int
重载,但在运行时它实际上是在使用int?
overload because the confData
list might be empty. 重载,因为
confData
列表可能为空。 If I explicitly tell it the return type is int?
如果我明确告诉它返回类型是
int?
it returns null
for the empty list entries, and I can later null-coalesce the null
s to zero. 它返回
null
的空列表项,以后我可以空聚结null
秒至零。
Instead of trying to get EF to generate a SQL query that returns 0 instead of null, you change this as you process the query results on the client-side like this: 无需尝试让EF生成返回0而不是null的SQL查询,而是在像这样处理客户端的查询结果时进行更改:
var results = from r in roomsData.AsEnumerable()
select new
{
r.Room,
r.ConferenceCount,
ParticipantCount = r.ParticipantCount ?? 0
};
The AsEnumerable()
forces the SQL query to be evaluated and the subsequent query operators are client-side LINQ-to-Objects. AsEnumerable()
强制对SQL查询进行求值,随后的查询运算符是客户端LINQ-to-Objects。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.