根据previous question,我得到了以下LINQ表达式。
Events.Where(Function(e) e.EventDate >= Date.Today) _
.OrderByDescending(Function(e) (((e.EventVotes.Sum(Function(s) s.Vote)) * 2) + (e.Comments.Count))) _
.Skip(0) _
.Take(5)
哪个转换为以下SQL
-- Region Parameters
DECLARE @p0 DateTime2 = '2011-01-17 00:00:00.0000000'
DECLARE @p1 Int = 2
DECLARE @p2 Int = 0
DECLARE @p3 Int = 5
-- EndRegion
SELECT [t3].[ID], [t3].[UserID], [t3].[RegionID], [t3].[LocationID], [t3].[Title], [t3].[Description], [t3].[EventDate], [t3].[URL], [t3].[Phone], [t3].[TicketPriceLow], [t3].[TicketPriceHigh], [t3].[DatePosted], [t3].[isHighlighted]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY (((
SELECT SUM([t1].[Vote])
FROM [dbo].[EventVotes] AS [t1]
WHERE [t1].[EventID] = [t0].[ID]
)) * @p1) + ((
SELECT COUNT(*)
FROM [dbo].[Comments] AS [t2]
WHERE [t2].[EventID] = [t0].[ID]
)) DESC) AS [ROW_NUMBER], [t0].[ID], [t0].[UserID], [t0].[RegionID], [t0].[LocationID], [t0].[Title], [t0].[Description], [t0].[EventDate], [t0].[URL], [t0].[Phone], [t0].[TicketPriceLow], [t0].[TicketPriceHigh], [t0].[DatePosted], [t0].[isHighlighted]
FROM [dbo].[Events] AS [t0]
WHERE [t0].[EventDate] >= @p0
) AS [t3]
WHERE [t3].[ROW_NUMBER] BETWEEN @p2 + 1 AND @p2 + @p3
ORDER BY [t3].[ROW_NUMBER]
我现在的问题是,在某些事件没有任何投票或评论时进行订购。
这是EventVotes表的样子(完整的)
| UserID | EventID | Vote |
| 1 | 51 | 1 |
| 1 | 52 | 1 |
| 2 | 52 | 1 |
| 1 | 53 | 1 |
| 2 | 53 | -1 |
| 3 | 53 | -1 |
评论表是完全空的,所以因为我们只是在它上面做Count
,我们可以假设一切都回来了。
现在,当我运行上面的查询时,结果顺序如下
52
51个
53个
1
2
3
什么时候“应该”
52
51个
1
2
3
53
因为事件编号53的投票数为“-1”,而事件编号1,2和3的投票数为“0”
任何人都可以帮忙弄清楚如何增强Linq表达式来解释尚未投票的事件吗?
这是截图
好的,所以我将LinqPad中的查询简化为此,结果是我只得到了三个结果。
Events.OrderByDescending(Function(e) (((e.EventVotes.Sum(Function(s) s.Vote)) * 2) + (e.Comments.Count)))
这告诉我的是,orderby只抓取这三个结果(51,52,53),然后它在订单子句之后附加其余的结果。我需要想办法在Lambda表达式中包含其余的“null”结果。
答案 0 :(得分:1)
这是一个C#解决方案。我试着把它翻译成VB,但我的VB技能(并且老老实实地想学习它)是零,我放弃了。我将尝试强调帮助翻译的关键点。
以下是完整的陈述:
context.Events.OrderByDescending(e => (((e.EventVotes.Sum(s => (int?)s.Vote) ?? 0) * 2) + e.Comments.Count))
重要的是s.Vote
首先被转换为可以为空的整数,以便Sum()
的结果是可以为空的整数。可空的结果允许您显式检查null,如果结果确实为null,则对其余计算使用零。
对于VB转换目的,??
是一个C#null-coalesce运算符,其中(例如)myNullableIntVar ?? 0
求值为myNullableIntVar的值,或者如果它为null,则为0。
这是上面语句生成的SQL,FWIW:
exec sp_executesql N'SELECT [t0].[EventID], [t0].[Name]
FROM [dbo].[Events] AS [t0]
ORDER BY ((COALESCE((
SELECT SUM([t2].[value])
FROM (
SELECT [t1].[Vote] AS [value], [t1].[EventID]
FROM [dbo].[EventVotes] AS [t1]
) AS [t2]
WHERE [t2].[EventID] = [t0].[EventID]
),@p0)) * @p1) + ((
SELECT COUNT(*)
FROM [dbo].[Comments] AS [t3]
WHERE [t3].[EventID] = [t0].[EventID]
)) DESC',N'@p0 int,@p1 int',@p0=0,@p1=2
我在下面添加了VB.NET版本 - 这完全符合预期。我试图做DirectCast(s.Vote, Integer?)
,但它提出错误,指出Integer
无法转换为Integer?
,所以我不得不采用这种方法。
Events.OrderByDescending(Function(e) (((If(e.EventVotes.Sum(Function(s) s.Vote),
e.EventVotes.Sum(Function(s) s.Vote),
0)) * 2) + e.Comments.Count))
导致此SQL查询
-- Region Parameters
DECLARE @p0 Int = 0
DECLARE @p1 Int = 2
-- EndRegion
SELECT [t0].[ID], [t0].[UserID], [t0].[RegionID], [t0].[LocationID], [t0].[Title], [t0].[Description], [t0].[EventDate], [t0].[URL], [t0].[Phone], [t0].[TicketPriceLow], [t0].[TicketPriceHigh], [t0].[DatePosted], [t0].[isHighlighted]
FROM [dbo].[Events] AS [t0]
ORDER BY ((
(CASE
WHEN (CONVERT(Bit,(
SELECT SUM([t1].[Vote])
FROM [dbo].[EventVotes] AS [t1]
WHERE [t1].[EventID] = [t0].[ID]
))) = 1 THEN (
SELECT SUM([t2].[Vote])
FROM [dbo].[EventVotes] AS [t2]
WHERE [t2].[EventID] = [t0].[ID]
)
ELSE @p0
END)) * @p1) + ((
SELECT COUNT(*)
FROM [dbo].[Comments] AS [t3]
WHERE [t3].[EventID] = [t0].[ID]
)) DESC