【问题标题】:Avoid LINQ with Let keyword doing self-loop避免使用 Let 关键字进行自循环的 LINQ
【发布时间】:2011-04-01 08:14:37
【问题描述】:

我有三个表 Student、TimeSheet 和 TimeRecord。

Talbe 列:

  • 学生:StudentId、AssignedId、FirstName、 姓氏

  • TimeSheet:TimeSheetId、StudentId、IsArchive、IsComplete

  • TimeRecord: TimeRecordId,TimeSheetId, BonusHour(type int), CreationDate

表关系:

  • 学生 1:N 时间表 (FK StudentId)
  • TimeSheet 1:N TimeRecord (FK TimeSheetId)

学生样本数据:

StudentId、AssignedId、FirstName、LastName

  • 100、741、宏、约翰
  • 101 , 742 , 宏 , 边
  • 102、743、莎拉、柠檬 和儿子继续……

时间表样本数据:

TimeSheetId、StudentId、IsArchive、IsComplete

  • 187、100、真、假
  • 196、101、真、假
  • 195、102、真、假
  • 199、100、真、真
  • 200、102、真、真

TimeRecord 样本数据:

TimeRecordId、TimeSheetId、BonusHour、CreationDate

  • 1 , 187 , 1 , 7/18/2010 10:23:25 PM
  • 2 , 196 , 2 , 7/19/2010 2:23:25 PM

  • 3 , 187 , 1 , 8/1/2010 2:5:25 AM

  • 4 , 187 , 3 , 8/9/2010 12:23:13 PM

  • 5 , 196 , 0 , 7/20/2010 6:15:25 PM

  • 6 , 196 , 2 , 9/18/2010 2:23:25 PM

  • 7 , 195 , 3 , 8/18/2010 2:23:25 PM

  • 8 , 199, 4 , 7/18/2010 2:23:25 PM

实际上,我正在尝试获取每个学生的每月总奖金小时数。

    Dim query = From s In db.Students _
                 Let pair = (From ts In db.TimeSheets _
          Join tr In db.TimeRecords On tr.TimeSheetId Equals ts.TimeSheetId _
    Where ts.IsArchive = False And ts.IsCompleted = False And tr.TimeOut IsNot Nothing _
    Group By key = New With {ts.StudentId, .MonthYear = (tr.CreationDate.Value.Month & "/" & tr.CreationDate.Value.Year)} Into TotalHour = Sum(tr.BonusHour)) _
                From part In pair _
                Select New With {.stId = s.AssignedId, .MonthYear = part.key.MonthYear, .TotalHour = part.TotalHour}

此查询循环遍历“pair”元素并将其分配给每个学生。

AssignedId , MonthYear, TotalHour - 741, 6/2010 , 5 - 742, 6/2010 , 5 - 743,2010 年 6 月,5 - 744, 6/2010 , 5 - 745, 6/2010 , 5 - 741, 7/2010 , 8 - 742, 7/2010 , 8 - 743, 7/2010 , 8 - 744, 7/2010 , 8 - 745, 7/2010 , 8

等等..直到“pair”元素的最后一个结果。

那么,正确的结果应该是这样的:

- 741, 6/2010 , 5 - 742, 6/2010 , 8 - 743, 6/2010 , 9 - 744, 6/2010 , 10 - 745, 6/2010 , 15

或者像这样:

AssignedId ,例如月/年:

已分配 ID,2010 年 7 月,2010 年 8 月 - 741、8 小时、2 小时 - 742、3 小时、4 小时 - 743、3 小时、1 小时 - 和儿子..

您能帮我更正我上面的查询吗?欢迎使用 C# 或 VB.NET 提出任何建议。 谢谢。

【问题讨论】:

  • 不清楚 9、10 和 15 的来源。您能否发布更多详细信息,或者源表布局的屏幕截图?
  • 请看我的更新。我也包括了表格结构。

标签: c# vb.net linq linq-to-sql .net-3.5


【解决方案1】:

我会考虑从 TimeRecord 本身开始,而不是从学生开始。只要您的 Linq To Sql 映射正确(并且关系到位),您就已经有了一些有用的关系属性可供使用。以下是我形成查询的方式,但在迁移到 VB 时可能需要进行一些更改。

var hours = from tr in db.TimeRecords
            where !tr.TimeSheet.IsArchive && !tr.TimeSheet.IsCompleted && tr.TimeOut != null
            group tr.BonusHour by
                new {
                        tr.TimeSheet.Student,
                        MonthYear = tr.CreationDate.Value.Month + "/" + tr.CreationDate.Value.Year
                    }
            into g
            select new {g.Key.Student.AssignedId, g.Key.MonthYear, TotalHour = g.Sum()};

如果您的模型不同,请告诉我,但这个想法应该适合您。

【讨论】:

    【解决方案2】:

    在顶层,您的查询由两个结果集组成:

    1. db.Students
    2. 对,由Let 子句定义。

    由于您在顶层有两个 From 子句(一个用于 db.Students,一个用于 pair),并且没有 JoinWhere 子句将一个与另一个关联起来,LINQ 构造了本质上是它们之间的交叉连接。

    我认为您想将第二个结果集(对)与第一个结果集(db.Students)Join,或者以其他方式在顶级Where 子句中指示它们的关联。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 2023-03-27
      相关资源
      最近更新 更多