NHibernate QueryOver值集合

时间:2011-09-19 19:08:07

标签: nhibernate queryover

我有一个使用NH 3.1的项目,到目前为止一直使用QueryOver语法。

这个项目的一个方面存在于一个组织范围的数据库中,我只读访问并使用完全不同的DBMS(Oracle vs MSSQL)。所以我使用标准的多对多表将我的对象(Foos)的引用存储到它们的对象(Bars)

FooBars
FooID int not null PK
BarID int not null PK

而我的域对象,而不是Iset<Bar>而是有一个ISet<int> BarIDs,它被手动映射到FooBars表。这可以防止NH尝试做不可能的事情并一直加入Bars表(我可以使用BarRepository.Get()稍后检索Bars的细节,如果我需要它们,在这种情况下,我会不,因为我只需要ID来过滤返回的对象列表。

鉴于IList<int> SelectedBars如何撰写QueryOver<Foo>,其中BarIDs包含SelectedBars中的任何元素?

SQL就像

...FROM foos INNER JOIN foobars on foo.fooID = foobars.fooID WHERE barID IN ( ... )

3 个答案:

答案 0 :(得分:2)

QueryOver无法实现。两年前,我有一个similar question about filtering value collections。 (注意:QueryOver基于Criteria API)。

我不是百分百肯定,但它可能适用于HQL。它更强大。

您可以在QueryOver条件中包含SQL语句。

我真的不明白为什么你不将它映射为实体列表。有延迟加载以避免不必要的加载 - 虽然有时会有一些折衷。您无需访问数据库即可访问NH代理的ID。映射ID通常会让生活更加艰难。

答案 1 :(得分:1)

尝试:

session.QueryOver<Foo>()
       .JoinQueryOver(x => x.FooBars)
       .WhereRestrictionOn(x => x.BarId).IsIn( ... )

答案 2 :(得分:0)

3年后,我回来报告我是如何解决这个问题的。

public class Foo :Entity {
    public virtual ISet<FooBar> BarIDs { get; protected internal set; }
 } ...

public class FooBar :Entity {
    protected internal FooBar() { }
    protected internal FooBar(Foo f, int BarID) { ... }
    public virtual Foo Foo { get; protected internal set; }
    public virtual int BarID { get; protected internal set; }
}

这基本上是斯特凡所建议的,以及相关帖子中暗示的内容。您只需要花费额外实体并引用它的开销。请记住,我存储BarID而不是完整的Bar对象,因为我处理两个数据库之间的硬边界:条形图存储在与Foos不同的平台上的完全不同的数据库中。当然,除了告诉Foo有一个ISet<Bar>之外你还好得多。

通过SelectedBarIDs查找Foos非常简单,就像Thilak建议的那样:

session.QueryOver<Foo>().JoinQueryOver<FooBar>(f => f.BarIDs).
    WhereRestrictionOn(b => b.BarID).IsIn(...)...

这是一个有趣的问题,跨越这样的数据库边界。我不能说我喜欢这样做,但是如果其他人打算花时间维护一个酒吧列表并让它供我使用,那对我来说将是一个巨大的资源浪费相同。因此,使用包装器类的效率很低,这是非常容易证明的成本。