【问题标题】:Criteria API With clause in many-to-many relationship多对多关系中的 Criteria API With 子句
【发布时间】:2011-07-01 17:34:11
【问题描述】:

NHibernate 3 introduced the With clause 用于标准 API。我正在尝试使用它来限制多对多关系上的连接,而 NHibernate 正在将附加连接限制应用于链接表而不是正确的表。

我在 Player 和 Address 之间有一个多对多的关系,我想通过限制 Address.IsMailingAddress 返回一个 Player 及其邮寄地址。在 where 子句中限制 IsMailingAddress 不会返回没有邮寄地址(或根本没有地址)的记录,因此我需要在联接中限制它。下面的代码被简化了,我不能用HQL。

查询:

var target = session.CreateCriteria<Player>()
    .SetProjection(Projections.Property("PlayerId"))
    .CreateAlias("Addresses", "ad", JoinType.LeftOuterJoin, Restrictions.Eq("ad.IsMailingAddress", true))
    .Add(Restrictions.Eq("LastName", "Anonymous"))
   .List();

生成 SQL:

SELECT this_.PlayerId as y0_
FROM   dbo.VPlayerExisting this_
       left outer join dbo.LinkPlayAddr addresses3_
         on this_.PlayerId = addresses3_.PlayerId
            and (ad1_.MailingAddressFlag = 1 /* @p0 */)
       left outer join dbo.VAddress ad1_
         on addresses3_.AddressId = ad1_.AddressId
            and (ad1_.MailingAddressFlag = 'Anonymous' /* @p1 */)
WHERE  this_.Name_Last = @p2

MailingAddressFlag(映射到 IsMailingAddress 的列)在不存在的多对多链接表中受到限制,并且 LastName 限制应用于地址表的联接。确实会发出查询,但数据库服务器当然会引发异常。

这是一个错误、不受支持还是我做错了?

【问题讨论】:

  • 我认为这是一个错误,但我找到了一个简单的解决方法。 25分给第一个能见树不见林的人。提示:一个玩家可以链接到多个地址,但这些地址中只有一个是邮寄地址。

标签: nhibernate criteria criteria-api icriteria


【解决方案1】:
var target = session.CreateCriteria<Player>()
    .CreateAlias("Addresses", "ad", JoinType.InnerJoin)
    .Add(Restrictions.Eq("LastName", "Anonymous"))
    .Add(Restrictions.Eq("ad.IsMailingAddress",true))
    .List();

在 IsMailingAddress 的限制下只内连接到邮寄地址?

应带回玩家(LastName 为“匿名”)及其 MailingAddress,其中他们有一个地址,并且该地址被标记为 IsMailingAddress。

【讨论】:

  • 如果没有地址或没有设置了 IsMailingAddress 的地址,则不返回任何玩家。第一个问题(没有行)很容易通过左连接解决,第二个问题更难。目标是返回玩家及其邮寄地址(如果存在),否则返回玩家地址为空。
  • 玩家是否可以只有一个未标记为邮寄地址的地址?
  • 您是否有机会回答您自己的问题,以便我了解您的解决方法?
【解决方案2】:

解决方案如下。应该只有一个设置了 IsMailingAddress 的地址,因此如果有一个或没有使用内部连接,则 or 条件允许连接成功。

var target = session.CreateCriteria<Player>()
    .SetProjection(Projections.Property("PlayerId"))
    .CreateAlias("Addresses", "ad", JoinType.InnerJoin)
    .Add(RestrictionsOr(Restrictions.Eq("ad.IsMailingAddress", true), Restrictions.IsNull("ad.AddressId")))
    .Add(Restrictions.Eq("LastName", "Anonymous"))
   .List();

【讨论】:

  • 您使用的是什么数据库?你能把 SQL 贴出来吗?
猜你喜欢
  • 2017-01-20
  • 1970-01-01
  • 2010-10-17
  • 2016-12-31
  • 1970-01-01
  • 2021-10-18
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多