vb.net - 应用于 edmx 实体数据模型时,LINQ 中的自联接失败
问题描述
我的 EF 模型中有以下两个表。一个设备可能有零个、一个或多个数据校准。
表“Equipo”:此表包含设备。主键是equioid
Id | equipoId | Description
1 9474
2 9473
3 9475
表“CalibracionVerificacion”:此表包含每个设备的校准数据(设备数据校准)。主键是 ID。
Id | equipoId | magnitudId | fechaPrevista
1 9474 0402 2020-05-01 00:00:00.000
2 9474 0808 2020-01-01 00:00:00.000
3 9474 0101 2019-12-19 00:00:00.000
4 9473 2001 2018-02-08 00:00:00.000
5 9473 1901 2019-05-23 00:00:00.000
6 9473 1901 2017-08-17 00:00:00.000
7 9472 0808 2020-11-11 00:00:00.000
8 9472 0101 2019-01-01 00:00:00.000
我需要遍历表 Equipo 中的每个设备并为每个设备执行以下步骤:
- 在设备数据校准中,按 magnitudId 分组,并为每个 magnitudId 获取最近的 fechaPrevista(注意同一设备可能重复幅度)。
- 一旦我有了每个幅度 (magnitudId) 的最新日期和时间 (fechaPrevista),我想获得最旧的 fechaPrevista
所以我执行下面的 LINQ 表达式:
LINQ 表达式:
Dim eq = db.Equipo
For Each equipo As Equipo In eq
Dim fechaPrevista As DateTime? =
(From c In equipo.CalibracionVerificacion
Join c2 In (From c3 In equipo.CalibracionVerificacion
Where c3.equipoId = equipo.equipoId AndAlso Not (String.IsNullOrWhiteSpace(c3.magnitudId))
Group c3 By c3.magnitudId Into cgroup = Group
Select New With
{
Key .MagnitudID = magnitudId,
Key .MaxDate = cgroup.Max(Function(x) x.fechaPrevista)
}
) On New With {.JoinProperty1 = c.magnitudId, .JoinProperty2 = c.fechaPrevista} Equals
New With {.JoinProperty1 = c2.MagnitudID, .JoinProperty2 = c2.MaxDate}
Where c.equipoId = equipo.equipoId
Select c).Min(Function(d) d.fechaPrevista))
// Do something with fechaPrevista
Next
我通过直接指向数据库检查了 LINQPad 5 中的相同 LINQ 表达式,它工作正常。
例如,考虑到上表,对于equipoId = 9474,我想获得最早的日期和时间,即 2019-12-19 00:00:00.000,但由于 fechaPrevista,我什么也没得到。
由于我无法调试上述 LINQ 表达式,因此我将查询分解为多个部分。我一直在调试上面的 LINQ 表达式,分为两部分:内部和外部 Linq 表达式。对于下面的内部 Linq 表达式:(假设在此示例中,equipo.equipoId = 9474):
Dim c23 = From c3 In equipo.CalibracionVerificacion
Where c3.equipoId = equipo.equipoId AndAlso Not (String.IsNullOrWhiteSpace(c3.magnitudId))
Group c3 By c3.magnitudId Into cgroup = Group
Select New With
{
Key .MagnitudID = magnitudId,
Key .MaxDate = cgroup.Max(Function(x) x.fechaPrevista)
}
...我得到了正确的结果。它正在工作并返回以下结果:
所以内部 LINQ 表达式运行良好。问题在于外部 LINQ 表达式,自联接失败,然后返回 Nothing 作为结果。我不懂为什么。有任何想法吗?
基本上,翻译成 SQL Server 的 LINQ 表达式是(例如,为了简化,一个equipoId 是):
-- Region Parameters
DECLARE @p0 Int = 9474
DECLARE @p1 Int = 9474
-- EndRegion
SELECT MIN([t0].[fechaPrevista]) AS [value]
FROM [eq].[CalibracionVerificacion] AS [t0]
INNER JOIN (
SELECT MAX([t1].[fechaPrevista]) AS [value], [t1].[magnitudId]
FROM [eq].[CalibracionVerificacion] AS [t1]
WHERE [t1].[equipoId] = @p0
GROUP BY [t1].[magnitudId]
) AS [t2] ON ([t0].[magnitudId] = [t2].[magnitudId]) AND ([t0].[fechaPrevista] = [t2].[value])
WHERE [t0].[equipoId] = @p1
解决方案
使用 LINQ,以声明方式(即,根据期望的结果)进行思考比以命令方式(即,控制流)进行思考更有帮助。据我所知,最终您希望迭代具有以下属性/字段的结果集:
- 等价
- 幅度标识
- 第一次 fechaPrevista
- 最后 fechaPrevista
我可能误会你了。从您的描述中,不清楚您是否想要每组的最后一个 fechaPrevista 与所有实体/记录的最后一个。此外,我在这里假设您希望跳过 Equipo 中没有 CalibracionVerificacion 中没有子项的任何行。如果我在这里的假设是准确的,那么这应该会让你得到你所追求的:
Dim data = db.CalibracionVerificacion
Dim qry = (From item in data group by grp = New With {Key item.equipoId, Key item.magnitudId} into finalGrp = Group
Select New With
{
.equipoId = grp.equipoId,
.magnitudId = grp.magnitudId,
.firstFechaPrevista = finalGrp.Min(function(g) g.fechaPrevista),
.lastFechaPrevista = finalGrp.Max(function(g) g.fechaPrevista)
}).ToList
For each item in qry
'do something
next
推荐阅读
- swift - 通过 Swift 泛型初始化 SwiftUI 视图
- python - 知道了速度场,我如何才能找到该速度场内“无质量”粒子的轨迹?
- flutter - 错误:NoSuchMethodError:在 null 上调用了方法“[]”。接收者:null 尝试调用:[]("name")
- angular - 使用来自 typescript 的 html 元素以角度包装组件
- javascript - 我想为某些数字和字符创建一个正则表达式,这些数字和字符多次出现并且 [number-number] 出现 0 次或多次。下面是我的正则表达式
- powershell - 通过 Powershell 将 office365 组添加到 Sharepoint 网站集管理员
- javascript - 如何使用自动逗号计算输入
- web-services - 请求有关自动 glpi 操作的帮助
- python - pandas DF 不在索引 = 键的字典列表中
- reactjs - reactjs 中的一般 400/500 错误处理