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 の max エントリは、レポートが表示される最新のレコードであることを示します。レポートは、タイトルまたは ReportItems にグループ化されます。これらのレポート アイテムには、タイトルと関連するレポートが含まれます。これらの reportItems は、JSON を目的の形式で出力できるように ReportList に保持され、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

あなたが提供する詳細は、完全ではありませんが、それをはるかに明確にするので、2つの選択肢を示します。非常に簡潔で包括的な構文が可能になるため、ナビゲーションプロパティが便利です。

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

または(でグループ化されているように見えるためTitleReportItems

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 fluent構文では、要約するとSelectMany()sになります。

ご覧のように、私はまだその役割を理解することはできませんLotTitle、代替案があなた自身の仕様に合わせて成形するための実質を与えることを願っています。

于 2012-09-07T22:41:37.360 に答える
0

データベーススキーマを変更して、少しフラットにし、多くの分岐を削除しました。

レポートがルートになり、レポートに添付されるタイトルのテーブルがあります。

提案してくれたすべての人に感謝します!

于 2012-09-13T19:37:08.943 に答える
0

私がそれを正しく理解していれば、seedLot による最新のレポートが必要な場合は、次を使用します。

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

ReportItem と ReportList を結果に含めない場合、なぜ ReportItem と ReportList が必要なのかよくわかりません。

于 2012-09-07T21:02:45.533 に答える
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 を使用してそのグループの構文が正しいと 100% 確信しているわけではありません (日常的にグループ化をあまり行っていません)。また、LINQ プロバイダーが Max をサポートしていない場合 (または、Contains をサポートしている必要があります)、クライアント側ですべてをプルすることになり、大量のデータをネットワーク経由でプッシュすることになります。

于 2012-09-07T22:09:43.333 に答える