将SQL语句转换为LINQ-To-SQL

时间:2012-09-07 15:06:03

标签: c# sql linq

我是否可以将以下内容转换为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的问题是它返回标题已更改的条目。在数据库中,我保留了所有记录的历史记录(因此需要第一个创建日期顺序下降。当我将报告从标题x更改为标题y时,它显示在两个标题下,当我只想要最新记录时因此是标题y下的那个。

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

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

这是我的类结构(也模仿数据库结构)

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;}
}

谢谢, DMAN

4 个答案:

答案 0 :(得分:0)

如果我理解正确,那么你想要seedLot的最新报告,然后我会使用下一个:

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

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

答案 1 :(得分:0)

阿。我知道了。您的内部联接正在剔除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;

我不是百分之百,我已经使用Contains在该组中获得了正确的语法(我不会在日常工作中进行大量的分组)。如果LINQ提供程序不支持Max(或包含,虽然它应该),那么它将拉出客户端的eveything,这是很多数据来推送电线。

答案 2 :(得分: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()

或(因为您似乎在Title中按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。

如您所见,我仍然无法弄清楚LotTitle的作用,但我希望替代方案可以根据您自己的规格提供一些实质内容。

答案 3 :(得分:0)

将数据库架构更改为sorta将其展平,取消了很多分支。

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

感谢大家的建议!