4

使用 LINQ-to-NHibernate 有没有办法缩小FetchMany()返回的范围?

给定以下类结构

public class Foo
{
  public virtual int Id { get; set; }
  public virtual IList<Bar> Bars { get; set; }
}
public class Bar
{
  public virtual string Description { get; set; }
}

我怎样才能做到这一点:

session.Query<Foo>()
  .Where(foo => foo.Id > 30)
  .FetchMany(foo => 
    foo.Bars.Where(bar => bar.Description.StartsWith("x")));

NHibernate 将返回所有 Id > 30 的 Foo,对于那些 Foo 的所有附加 Bar,Bar 的描述以字母“x”开头?

我发现了一些使用旧QueryOver()东西的帖子,但我明确地想使用 NHibernate 的 LINQ 提供程序。

有任何想法吗?


更新

我想我需要澄清我想要的结果。

<Foo Id="1">
  <Bar Description="x1"/>
  <Bar Description="b1"/>
</Foo>
<Foo Id="31">
  <Bar Description="x2"/>
  <Bar Description="x3"/>
  <Bar Description="b2"/>
</Foo>
<Foo Id="32">
  <Bar Description="b3"/>
</Foo>

从上面概述的数据中,我期望得到以下结果

<Foo Id="31">
  <Bar Description="x2"/>
  <Bar Description="x3"/>
</Foo>
<Foo Id="32"/>

附加的 Where 子句应该只对 Bar 有效!它不应该进一步缩小 Foo 的列表!只是减少FetchMany()回报。

4

4 回答 4

1
var query = from foo in session.Query<Foo>()
            where foo.Id >30
            from bar in foo.Bars
            where bar.Description.StartsWith("x")
            select new { Id = foo, Bar = bar};
var results = query.ToList().ToLookup(x => x, x => x.Bar);
foreach(var foo in results.Keys)
{
   var barsWhichStartWithX = results[foo];
   //DO STUFF
}

虽然这可能会产生低效的 SQL(我不使用 nHibernate,所以我不知道)。你也可以试试这个......上面也会错过没有酒吧的 foos 。

var foosQuery = session.Query<Foo>().Where(foo => foo.Id > 30);
var foos = foosQuery.Future();
var barsQuery = from f in foosQuery
                from bar in foo.Bars
                select new { Id = foo.Id, Bar = bar};
var foosDict = foos.ToDictionary(x => x.Id);
var bars = barsQuery.ToList().ToLookup(x => foosDict[x.Id], x => x.Bar);
foreach(var foo in foos)
{
   var barsWhichStartWithX = bars[foo];
   //DO STUFF
}
于 2013-07-19T01:56:50.907 回答
1

我相当确定您对当前的 linq 提供程序不走运 - 但​​对于非 linq(和横切)选项,您可能想看看 NHibernate 中包含的过滤器功能 - 它可能是在大型/复杂项目中实施这一点的最佳选择。

于 2013-07-16T17:11:52.780 回答
0

也许不完全是您所追求的,但肯定值得考虑的是NHibernate.CollectionQuery库。

它允许您使用 Linq 在实体上查询未初始化的 NHibernate 集合 - 但需要额外的查询/往返来获取它们(与 FetchMany 不同,它在同一往返中获取整个集合)。

于 2013-07-15T17:08:39.407 回答
0

您将需要从子对象到父对象的引用。

var result = from foo in session.Query<Foo>().FetchMany(f => f.Bars)
             from bar in session.Query<Bar>()
             where foo.Id == bar.FooId && // FooId is missing in your entity
                   foo.Id > 30
                   bar.Description.StartsWith("x")
             select foo;
于 2013-07-16T14:01:30.397 回答