2012-09-07 109 views
6

我可以将以下代码转换为LINQ语句。将SQL语句转换为LINQ-to-SQL

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中的一个。

EDIT 对不起缺乏细节。我有保持信息有关的报告(seedlot作为一个标识符)一个报告表中。每当报告进行编辑时,一个新的记录插入(与更新旧版本相比),以保持历史记录在这种情况下,createdDate的最大条目表示报告是最近要显示的记录,然后将报告分组为标题或ReportItems。保留标题和相关报告。这些reportItems保存在ReportList中,例如th在我可以打印出所需格式的JSON,并且只包含由ReportItems链接到的状态列和ID。

如果将报告从标题a移至标题b,则会输入一条新记录,并将标题外键链接至所更改的标题。当发生这种情况时,上面给出的LINQ返回每个单独的ReportItem下的记录,它应该只返回标题b的最新条目(来自上面的示例)。除此之外,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;} 
} 

感谢, DMAN

+1

所以我正确理解seed_lot是区分真正独特的报告与另一个*和*报告遇到名称变化的区别?也就是说,就report_max_dates而言,重新命名的报告与真正独特(不相关)的报告没有区别? –

+0

请详细说明。解释你想要的。很难从SQL代码片断和错误的linq查询中推断出来。并解释一个报告的各个版本如何保存在一起。 –

+0

在我看来,你需要遍历一连串的更新记录,以获得基于seed_lot的化身的报告的* latest *版本,这可能会使LINQ版本(很多?)比它看起来更难。 –

回答

0

更改了数据库模式以使其变得平滑一点,取出了很多分支。

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

感谢所有的建议寿!

0

如果我的理解是正确的,那么您可以通过seedLot希望最新的报告,那么我d使用下一个:

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

不太清楚为什么你需要ReportItem和ReportList,如果你不把它们包括到结果,你可以遍历由他们与报告的导航属性。

+0

我需要ReportList和ReportItems,以便JSON对象按照接收端的要求进行格式化。我最内在的LINQ声明已经这样做了。 – DMCApps

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(或包含,尽管它应该),那么它将会拉动客户端的一切,并且这是大量的数据来推动网络。

+0

对不起,这名国家人并不完全符合我的要求。尽管他们确实返回了没有重复的顶级报告(我的内部linq语句也已经这样做了),我需要的是报告返回的报告在其各自的标题下,而不是作为报告列表,而是作为reportList包含所有报告reportItems,然后包含该标题的所有相应报告。 – DMCApps

+0

啊。你所要做的就是将返回值改为rl而不是r。 –

+0

仍然不是:(这将返回6个报告列表(每个报告一个)。我需要的是一个报告列表,其中包含2个reportItems(因为我有2个标题),每个列表包含3个报告(因为我有3个报告每个标题)请注意,这些值是特定于我目前如何设置数据库,并将随着更多数据的变化而变化。非常感谢您继续努力! – DMCApps

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() 

或者(因为你在ReportItems看起来是一组由Title):

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的作用,但我希望这些替代品能够提供一些物质来塑造你自己的规格。

+0

抱歉,这些陈述并不完全符合我的要求。尽管他们确实返回了没有重复的顶级报告(我的内部linq语句也已经这样做了),我需要的是报告返回的报告在其各自的标题下,而不是作为报告列表,而是作为reportList包含所有报告reportItems然后包含该标题的所有相应报告(具有最大日期)。 – DMCApps

+0

如果您希望将集合部分填充,您需要['DataLoadOptions'](http://msdn.microsoft.com/zh-cn/library/bb534361),特别是, 'AssociateWith'。或者您应该创建双向导航属性,以便您可以通过报告获取reportItem和reportList。 –