6

我可以帮忙将以下内容转换为 LINQ 语句吗?

SELECT reports.* FROM [dbo].[ReportLists] rl
INNER JOIN [dbo].[ReportItems] ri ON rl.Id = ri.ReportListId
INNER JOIN [dbo].[Reports] reports ON ri.Id = reports.ReportItemId
WHERE
    reports.createdDate
IN (
    SELECT 
        MAX(report_max_dates.createdDate) 
    FROM 
        [dbo].[Reports] report_max_dates
    GROUP BY 
        report_max_dates.seedLot
    )

目前我把它归结为:

db.ReportLists.Select(rl => db.ReportItems
                            .Where(ri => ri.ReportListId == rl.Id)
                            .Select(ri => db.Reports
                                          .Where(r => r.ReportItemId == ri.Id)
                                          .GroupBy(r => new { r.seedLot })
                                          .Select(g => g.OrderByDescending(x => x.createdDate).FirstOrDefault())));

上面的 LINQ 的问题是它返回的条目标题已更改。在数据库中,我保留所有记录的历史记录(因此需要在 createdDate 上按降序排列第一个。当我将报告从标题 x 更改为标题 y 时,当我只想要最新的记录时,它会显示在两个标题下因此成为标题 y 下的那个。

编辑 对不起,缺乏细节。我有一个报告表,其中包含有关报告的信息(seedlot 是标识符)。每当编辑报告时,都会插入一条新记录(而不是更新旧记录),以便保留历史记录。在这种情况下,createdDate 的最大条目表示报告是要显示的最新记录。然后将报告分组为标题或 ReportItems。这些报告项目包含标题和相关的报告。这些reportItems 保存在ReportList 中,这样我就可以以所需的格式打印出JSON,并且只包含一个状态列和由ReportItems 链接的id。

如果将报告从标题 a 移动到标题 b,则会输入一条新记录,其中标题外键链接到它更改为的标题。当发生这种情况时,上面给定的 LINQ 在它应该只返回标题 b 的最新条目时返回每个单独的 ReportItem 下的记录(来自上面的示例)。除此之外,LINQ 语句仅返回 createdDate 的最新记录。

这是我的类结构(也模仿了 DB 结构)

public class ReportList {
    public int Id {get;set;}
    public string status {get;set;}
    public List<ReportItem> {get;set;}
}

public class ReportItem {
    public int Id {get;set}
    public string title {get;set;}
    public List<Report> {get;set;}
}

public class Report {
    public int Id {get;set;}
    public string Lot {get;set;}
    ... Other data ...
    public DateTime createdDate {get;set;}
}

谢谢,德曼

4

4 回答 4

0

如果我理解正确,那么您需要 seedLot 的最新报告,那么我将使用下一个:

from r in Reports
group r by r.CreateDate into g
select g.OrderByDescending(r1=>r1.CreateDate).FirstOrDefault()

如果您不将 ReportItem 和 ReportList 包含在结果中,则不太确定为什么需要它们,您可以使用 Report 的导航属性遍历它们。

于 2012-09-07T21:02:45.533 回答
0

啊。我懂了。您的 Inner Join 正在剔除 ReportItems 表中没有 Id 的记录和 ReportLists 表中没有 Id 的 ReportItems。由于您没有在 Linq 中使用内部连接语法,因此它们并不等效。你有没有试过这个:

var reports = from rl in db.ReportLists
              from ri in rl.ReportItems 
              from r in ri.Reports
              where (
                  from report in db.Reports
                  group report by report.seedLot into g
                  select g.Max(rep => rep.createdDate)).Contains(r.CreatedDate)
              select rl;

我不是 100% 我在包含的那个组上的语法是正确的(我没有每天做很多分组)。而且,如果 LINQ 提供程序不支持 Max(或 Contains,尽管它应该),那么它将拉取客户端的所有内容,并且需要通过网络推送大量数据。

于 2012-09-07T22:09:43.333 回答
0

您提供的详细信息使其更加清晰,尽管并非完全如此,因此我将提供两种选择。导航属性派上用场,因为现在可以使用非常简洁的综合语法:

from rl in context.ReportLists
from ri in rl.ReportItems
from r in ri.Reports
group r by r.Lot into g
select g.OrderByDescending(x => x.createdDate).FirstOrDefault()

或(因为您似乎按Titlein分组ReportItems):

from rl in context.ReportLists
from ri in rl.ReportItems
group ri by ri.Title into g
select g.Select(x => x.Reports
                      .OrderByDescending(x => x.createdDate).FirstOrDefault())

在幕后,这也会产生 SQL 连接,但您不需要笨拙的语法。在 linq 流利的语法中,它归结为SelectMany()s。

如您所见,我仍然无法弄清楚 and 的作用,LotTitle我希望替代方案能够提供一些实质内容来塑造您自己的规格。

于 2012-09-07T22:41:37.360 回答
0

更改了数据库模式以将其展平一点,并去掉很多分支。

报告现在是根,我只有一个附在报告上的标题表。

感谢大家的建议!

于 2012-09-13T19:37:08.943 回答