使用外连接的 Linq 查询没有 return 预期结果
Linq query with outer join doesn't return expected result
这可能很简单,但我就是做不对。
这是我的接线 - 事件与规则有多对多关系。事件可能有也可能没有规则。规则将有自己的详细信息。总之,我需要这样的对象:
object
- event
- rule (null)
- list of mappings (null)
所以,我将这些关系硬编码如下
Dim eventList As new List(Of [Event])
eventList.Add(new [Event]() With {.EventId = 1, .ClassId = 1, .TypeId = 1, .EventSequence = 2}) ' this is event without rules
eventList.Add(new [Event]() With {.EventId = 2, .ClassId = 1, .TypeId = 1, .EventSequence = 1})
eventList.Add(new [Event]() With {.EventId = 3, .ClassId = 1, .TypeId = 1, .EventSequence = 3})
Dim ruleEventList As New List(Of RuleEvent)
ruleEventList.Add(new RuleEvent() With {.Id = 1, .EventId = 2, .RuleId = 1})
ruleEventList.Add(new RuleEvent() With {.Id = 2, .EventId = 3, .RuleId = 1})
Dim ruleList As New List(Of Rule)
ruleList.Add(new Rule() With {.Id = 1, .EntityId = 1, .SearchId = 1})
Dim ruleDetailList As New List(Of RuleDetail)
ruleDetailList.Add(new RuleDetail() With {.Id = 1, .RuleId = 1, .Value = "aaa"})
ruleDetailList.Add(new RuleDetail() With {.Id = 2, .RuleId = 1, .Value = "bbb"})
这似乎是正确的,因为 2/3 工作正常。但这里是 LINQ
Dim eventRuleDetailList = _
From ev In eventList
From re In ruleEventList.Where(Function(r) r.EventId = ev.EventId).DefaultIfEmpty()
From rule In ruleList.Where(Function(r) re IsNot Nothing AndAlso r.Id = re.RuleId).DefaultIfEmpty()
From det In ruleDetailList.Where(Function(r) rule IsNot Nothing AndAlso r.RuleId = rule.Id).DefaultIfEmpty()
Group ev, rule, det By ev.EventId, ev.ClassId, ev.TypeId, ev.EventSequence
Into g = Group
Order By ClassId, TypeId, EventSequence
Select New With
{
.EventId = EventId,
.Event = g.First().ev,
.Rule = g.First().rule,
.Details = g.Select(Function(itm) itm.det) '<-- This is my glitch
}
结果似乎几乎正确,但有一个问题。我好像听不懂"Details"
For Each erd In eventRuleDetailList
Console.WriteLine("Event Id: {0}; Event Seq: {1}; Rule Id: {2}; Details: {3}",
erd.EventId,
erd.Event.EventSequence,
If (erd.Rule Is Nothing, "No Rules", erd.Rule.Id),
If (erd.Details Is Nothing, "No Details", "Yes Details")
)
Next
输出:
Event Id: 2; Event Seq: 1; Rule Id: 1; Details: Yes Details
Event Id: 1; Event Seq: 2; Rule Id: No Rules; Details: Yes Details
Event Id: 3; Event Seq: 3; Rule Id: 1; Mapped Details: Yes Details
问题来了。我做错了,因为 Event Id: 1
应该说 "No Details"。它有 "No Rules"
谢谢
以与规则相同的方式指示详细信息:
.Rule = g.First().rule,
.Details = g.First().det,
我成功了
这是 Select
需要稍微调整的部分
Select New With
{
.EventId = EventId,
.Event = g.First().ev,
.Rule = g.First().rule,
.Details = if(g.First().rule is nothing, nothing, g.Select(Function(itm) itm.det))
}
输出为
Event Id: 2; Event Seq: 1; Rule Id: 1; Details: Yes Details
Event Id: 1; Event Seq: 2; Rule Id: No Rules; Details: No Details
Event Id: 3; Event Seq: 3; Rule Id: 1; Mapped Details: Yes Details
这可能很简单,但我就是做不对。 这是我的接线 - 事件与规则有多对多关系。事件可能有也可能没有规则。规则将有自己的详细信息。总之,我需要这样的对象:
object
- event
- rule (null)
- list of mappings (null)
所以,我将这些关系硬编码如下
Dim eventList As new List(Of [Event])
eventList.Add(new [Event]() With {.EventId = 1, .ClassId = 1, .TypeId = 1, .EventSequence = 2}) ' this is event without rules
eventList.Add(new [Event]() With {.EventId = 2, .ClassId = 1, .TypeId = 1, .EventSequence = 1})
eventList.Add(new [Event]() With {.EventId = 3, .ClassId = 1, .TypeId = 1, .EventSequence = 3})
Dim ruleEventList As New List(Of RuleEvent)
ruleEventList.Add(new RuleEvent() With {.Id = 1, .EventId = 2, .RuleId = 1})
ruleEventList.Add(new RuleEvent() With {.Id = 2, .EventId = 3, .RuleId = 1})
Dim ruleList As New List(Of Rule)
ruleList.Add(new Rule() With {.Id = 1, .EntityId = 1, .SearchId = 1})
Dim ruleDetailList As New List(Of RuleDetail)
ruleDetailList.Add(new RuleDetail() With {.Id = 1, .RuleId = 1, .Value = "aaa"})
ruleDetailList.Add(new RuleDetail() With {.Id = 2, .RuleId = 1, .Value = "bbb"})
这似乎是正确的,因为 2/3 工作正常。但这里是 LINQ
Dim eventRuleDetailList = _
From ev In eventList
From re In ruleEventList.Where(Function(r) r.EventId = ev.EventId).DefaultIfEmpty()
From rule In ruleList.Where(Function(r) re IsNot Nothing AndAlso r.Id = re.RuleId).DefaultIfEmpty()
From det In ruleDetailList.Where(Function(r) rule IsNot Nothing AndAlso r.RuleId = rule.Id).DefaultIfEmpty()
Group ev, rule, det By ev.EventId, ev.ClassId, ev.TypeId, ev.EventSequence
Into g = Group
Order By ClassId, TypeId, EventSequence
Select New With
{
.EventId = EventId,
.Event = g.First().ev,
.Rule = g.First().rule,
.Details = g.Select(Function(itm) itm.det) '<-- This is my glitch
}
结果似乎几乎正确,但有一个问题。我好像听不懂"Details"
For Each erd In eventRuleDetailList
Console.WriteLine("Event Id: {0}; Event Seq: {1}; Rule Id: {2}; Details: {3}",
erd.EventId,
erd.Event.EventSequence,
If (erd.Rule Is Nothing, "No Rules", erd.Rule.Id),
If (erd.Details Is Nothing, "No Details", "Yes Details")
)
Next
输出:
Event Id: 2; Event Seq: 1; Rule Id: 1; Details: Yes Details
Event Id: 1; Event Seq: 2; Rule Id: No Rules; Details: Yes Details
Event Id: 3; Event Seq: 3; Rule Id: 1; Mapped Details: Yes Details
问题来了。我做错了,因为 Event Id: 1
应该说 "No Details"。它有 "No Rules"
谢谢
以与规则相同的方式指示详细信息:
.Rule = g.First().rule,
.Details = g.First().det,
我成功了
这是 Select
需要稍微调整的部分
Select New With
{
.EventId = EventId,
.Event = g.First().ev,
.Rule = g.First().rule,
.Details = if(g.First().rule is nothing, nothing, g.Select(Function(itm) itm.det))
}
输出为
Event Id: 2; Event Seq: 1; Rule Id: 1; Details: Yes Details
Event Id: 1; Event Seq: 2; Rule Id: No Rules; Details: No Details
Event Id: 3; Event Seq: 3; Rule Id: 1; Mapped Details: Yes Details