Vb.net 应用于edmx实体数据模型时,LINQ中的自连接失败

Vb.net 应用于edmx实体数据模型时,LINQ中的自连接失败,vb.net,entity-framework,linq,edmx,Vb.net,Entity Framework,Linq,Edmx,我的EF模型中有以下两个表。一个设备可能有零次、一次或多次数据校准 表“设备”:此表包含设备。主键是等轴面 Id | equipoId | Description 1 9474 2 9473 3 9475 表'CalibracionVerification':此表包含每个设备的校准数据(设备数据校准)。主键是Id Id | equipoId | magnitudId | fechaPrevista 1 9474 0402

我的EF模型中有以下两个表。一个设备可能有零次、一次或多次数据校准

表“设备”:此表包含设备。主键是等轴面

Id | equipoId  |  Description
1     9474
2     9473
3     9475
表'CalibracionVerification':此表包含每个设备的校准数据(设备数据校准)。主键是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中的每个设备,并对每个设备执行以下步骤:

  • 在设备数据校准中,按震级分组,并针对每个震级获得最新的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表达式。对于以下内部Linq表达式:(假设在本例中equipo.equipoId=9474):

    。。。我得到了正确的结果。它正在工作并返回以下结果:

    因此,内部LINQ表达式工作正常。问题在于外部LINQ表达式,自连接失败,结果是什么也不返回。我不明白为什么。有什么想法吗

    基本上,翻译成SQL Server的LINQ表达式是(例如,为了简化,一个Equaloid将是):


    使用LINQ时,声明式思考(即,根据期望的结果)比强制式思考(即,控制流)更有帮助。据我所知,最终您希望迭代具有以下属性/字段的resultset:

    • 等轴面
    • Magnitude
    • 第一费查普列维斯塔酒店
    • 最后的费查普雷维斯塔
    我可能误解了你。根据您的描述,不清楚您是否希望每个组的最后一个fechaPrevista与所有实体/记录的最后一个fechaPrevista。另外,我在这里假设您希望跳过Equipo中任何在CalibrationVerification中没有子项的行。如果我在这里的假设是准确的,这会让你得到你想要的:

    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
    

    不,没有两个fechaPrevista(第一个和最后一个)。只有一个fechaPrevista。在CalibracionVerification实体中,一个设备(Equaloid)可能有多个震级(magnitude)。在该示例中,同一设备没有重复的震级,但可能有。对于每个设备,我按震级分组并获取最新的日期时间(fechaPrevista)。例如,对于设备9474,我获取每个震级的最新日期时间:(04022020-05-01 00:00:00.000),(08082020-01-01 00:00:00.000),(01012019-12-19 00:00:00.000)在这组数据中,我得到了最早的日期时间(fechaPrevista),在本例中是“2019-12-19 00:00:00.000”。我对其余设备也这样做:9473和9472正如我所观察到的,内部linq表达式工作正常,但外部linq表达式应用连接失败。连接失败,但我不知道原因。请参阅最后更新的帖子。我在linq中尝试执行的操作与转换为SQL的操作相同服务器(为了简化,我只举了一个设备的例子)。
    -- 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
    
    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