【问题标题】:NHibernate QueryOver value collectionNHibernate QueryOver 值集合
【发布时间】:2023-04-02 07:50:01
【问题描述】:

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

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

FooBars
FooID int not null PK
BarID int not null PK

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

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

SQL 之类的

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

【问题讨论】:

    标签: nhibernate queryover


    【解决方案1】:

    QueryOver 不可能。两年前,我有一个similar question about filtering value collections。 (注意:QueryOver 基于 Criteria API)。

    我不能 100% 确定,但它可能适用于 HQL。它更强大。

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

    我真的不明白您为什么不将其映射为实体列表。有延迟加载以避免不必要的加载 - 尽管有时会有一些权衡。您无需访问数据库即可访问 NH 代理的 ID。映射 id 通常会使生活变得更加艰难。

    【讨论】:

    • 是的,我有这种虚幻的希望,也许两年后会有所改变。延迟加载不起作用,因为如果我不小心,它会尝试访问数据库,然后它会尝试将 MSSQL 数据库中的表连接到 Oracle 数据库。但我可以编写一个包装类“DummyBar”,仅将 ID 作为其唯一属性......只需让自动映射器忽略它。
    • 两个月后回到这...试图加入 BarProxy 表,a) 不存在 b) 即使它确实存在也是空的(真实数据在外部数据库中)。所以我想我们现在会尝试 HQL 或原始 SQL。
    【解决方案2】:

    试试:

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

    【讨论】:

      【解决方案3】:

      所以 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; }
      }
      

      这基本上是 Stefan 的建议,以及相关帖子中暗示的内容。您只需要承担编写额外实体并引用它的开销。请记住,我存储的是 BarIDs 而不是完整的 Bar 对象,因为我正在处理两个数据库之间的硬边界:Bars 存储在与 Foos 不同平台上的完全不同的数据库中。否则当然,你最好告诉 Foo 有一个ISet&lt;Bar&gt;

      通过 SelectedBarIDs 查找 Foos 很容易,就像 Thilak 建议的那样:

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

      这是一个有趣的问题,像这样跨数据库边界工作。我不能说我喜欢必须这样做,但是如果其他人要花时间维护 Bars 列表并使其可供我使用,那么这样做对我来说将是巨大的资源浪费.因此,包装类的效率低下很容易证明是合理的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多