0

このオブジェクト構造を考えると、WorkItem を戻すにはどうすればよいですか。それはレポート、行、および生徒ですが、生徒の名前が「ボブ」である行のみです (「アリス」を含む行は省略したいと思います)。 'および'クレア')。

WorkItem
----Report1 (WorkItem.Reports コレクションに保持)
--------ReportRow1 (Report.ReportRows コレクションに保持)
------------Student.Name = 'Alice'

--------ReportRow2 (Report.ReportRows コレクションに保持)
------------Student.Name = 'Bob'

--------ReportRow3 (Report.ReportRows コレクションに保持)
------------Student.Name = 'Claire'

(整形でごめんなさい)

このようなものがうまくいくと思っていましたが、それでも3行すべてが返されます

    WorkItem found = (from workItem in session.Query<WorkItem>()
                      from report in workItem.Reports
                      from row in report.ReportRows
                      where workItem.Id == 1 && row.Student.Name == "Bob"
                      select workItem)
                     .SingleOrDefault<WorkItem>();

更新 私もこれを試しましたが、実際にそれらを使用しようとしたときにのみ結果が返されると考えていましたが(そうです)、ログを見ると、それでも各学生の選択が行われます(「where」句が最後の foreach ループは、私が興味を持っていたものだけを返します。

    var query = from workItem in session.Query<WorkItem>()
                      where workItem.Id == 1 
                      select workItem;

    WorkItem found = query.SingleOrDefault<WorkItem>();

    foreach (var report in found.Reports)
    {
        foreach (var row in report.ReportRows.Where(x => x.Student.Name == "Bob"))
        {
            Console.WriteLine("--" + row.Student.Name);
        }
    }
 

これは、Ocelot20 の助けを借りて、現在の私の最高の試みです。

    var result = (from workItem in session.Query<WorkItem>()
                      .FetchMany(x => x.Reports) 
                      .ThenFetchMany(y => y.ReportRows.Where(z => z.Student.Name == "Bob"))
                  where workItem.Id == 1
                  select workItem);

唯一機能しないのは、学生名のWhere句です。それを削除すると、結果が返されます(行が多すぎますが)。where句を正しく取得できれば、必要なものが返されると思います

4

1 に答える 1

1

私がここで見ることができるものから、あなたはWorkItem. WorkItems返されるを制限する結合を行っていますが、まだ を選択しているだけで、WorkItem特定Reportsのなどを選択するように指示していませんReportRows。基本的に、クエリは次のように言っています。ボブ」と名付けました。「次に、適切な.WorkItemsIdWorkItemReportRows

私の推測では、あなたは次のようなことをしていると思います:

WorkItem found = (from workItem in session.Query<WorkItem>()
                      from report in workItem.Reports
                      from row in report.ReportRows
                      where workItem.Id == 1 && row.Student.Name == "Bob"
                      select workItem).SingleOrDefault<WorkItem>();

// Doing something to select `ReportRows` without filtering them:
var someSelection = found.Reports.First().ReportRows;

遅延読み込みの設定方法によっては、回線ReportRowsで呼び出すまでクエリすら行われません。someSelectionこの時点では、何をフィルタリングするかについて何も認識していません。ここにはいくつかのオプションがあります。WorkItemまず、次のようにロードしたら、2 番目のクエリでアイテムをフィルタリングできます。

// Filter on the second query:
var someSelection = found.Reports.First().ReportRows
                                         .Where(rr => rr.Student.Name == "Bob");

または、クエリを変更して、作業項目と関連する行を明示的に選択することもできます: select new { workItem, reportRows = // select specific rows with a where clause here. }.

最後に、選択したエンティティにプリロードする関連エンティティを指定する nhibernate 機能があります。エンティティ フレームワークを使用すると、関連するエンティティに句を追加できることは知ってWhereいますが、nhibernate を使用して、次のようなことができるかどうかを知りませんでした。

var customers = session.Query<Customer>()
                       .FetchMany(c => c.Orders.Where(o => o.Amount == 100);

これが機能する場合、これをクエリに適用して、名前が「Bob」WorkItemである関連行をロードするよう nhibernate に指示できます。Student

于 2013-01-21T15:07:30.190 に答える