2012-09-07 112 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。 –