【问题标题】:NHibernate Linq property-ref behaviorNHibernate Linq 属性引用行为
【发布时间】:2011-06-03 01:10:57
【问题描述】:

NHibernate Linq 正在生成一个未例外的查询。这是我的类映射:

public class OrderClassMap : ClassMap<Order> {
    public OrderClassMap() {
        Id(x => x.PersistenceId).Column("RowId").GeneratedBy.Assigned();
        Version(x => x.PersistenceVersion).Column("RowVersion");
        Map(x => x.OrderId).Generated.Insert().Not.Update();
        Map(x => x.OrderDate);
        References(x => x.Overseer).Column("OverseerId").PropertyRef(x => x.OverseerId);
        References(x => x.Overseer2).Column("OverseerId2").PropertyRef(x => x.OverseerId2);
    }
}

public class OverseerClassMap : ClassMap<Overseer> {
    public OverseerClassMap() {
        Id(x => x.PersistenceId).Column("RowId").Generated.Assigned();
        Version(x => x.PersistenceVersion).Column("RowVersion");
        Map(x => x.OverseerId).Generated.Insert().Not.Update();
        Map(x => x.Name);
        Map(x => x.Email);
    }
}

这是我的 Linq 查询:

var orders = session.Query<Order>()
                    .Where(o => ((o.Overseer.OverseerId == 1) || (o.Overseer.OverseerId == 2)))
                    .Fetch(o => o.Overseer)
                    .Fetch(o => o.Overseer2);

生成的 SQL 查询不是我所期望的。它不是进行左外连接,而是进行笛卡尔连接。下面是 NHibernate 生成的查询的简短示例:

SELECT ...
FROM Orders o LEFT OUTER JOIN
     Overseers v1 ON o.OverseerId = v1.OverseerId LEFT OUTER JOIN
     Overseers v2 ON o.OverseerId2 = v1.OverseerId,
     Overseers v3,
     Overseers v4
WHERE o.OverseerId = v3.OverseerId AND
      o.OverseerId2 = v4.OverseerId AND
      (v3.OverseerId = 1 OR v4.OverseerId = 1)

我期望的查询是这样的:

SELECT ...
FROM Orders o LEFT OUTER JOIN
     Overseers v1 ON o.OverseerId = v1.OverseerId LEFT OUTER JOIN
     Overseers v2 ON o.OverseerId2 = v1.OverseerId
WHERE (v1.OverseerId = 1 OR v2.OverseerId = 1)

我认为这样做是因为我有一个旧数据库并且在我的映射中使用 PropertyRef。有什么办法可以解决这种意外行为吗?为什么 NHibernate 会这样?这对我来说没有意义,因为通过指定 PropertyRef,我说的是“使用此键而不是主键”。

【问题讨论】:

  • 如果同时删除 .Fetch() 方法会发生什么?
  • 同样的事情,当我访问每个监督者的属性(延迟加载)时,只会为每个监督者发出一个单独的选择。
  • 您看到 FNH 生成的 hbm 映射了吗?它们是否正确构建?
  • 它们是正确构建的。当我使用 QueryOver api 而不是 linq 时,它按预期工作,但 QueryOver api 存在按嵌套属性排序的问题(即:无法按“Overseer.Name”排序)。

标签: nhibernate linq-to-nhibernate


【解决方案1】:

尝试使用 QueryOver,并指定左外连接。

【讨论】:

  • 我通过一个不是 NHibernate 特定的 IRepository 接口进行查询,所以我只有一个 IRepository for Query 的定义,但我可以考虑更改它。有没有其他方法可以用 Query 做到这一点?
  • QueryOver api 真的让我很沮丧。它似乎不能很好地处理嵌套属性,而且语法似乎很冗长。
【解决方案2】:

我不确定我是否理解您在这里想要实现的目标,但在我看来您的 PropertyRef 映射错误。

如果您希望Order 中的OverseerIdOverseerId2Overseers 表中的OvreseerId 列,那么您的property-ref 在这两种情况下都应为OverseerId

References(x => x.Overseer).Column("OverseerId").PropertyRef(x => x.OverseerId);
References(x => x.Overseer2).Column("OverseerId2").PropertyRef(x => x.OverseerId);

【讨论】:

  • 对不起。那是一个错字。在两者中都是 OverserId
  • @Wili,应该是 PersistenceId 而不是 OverseerId,请参阅我对答案的更新。
  • 我没有使用 PersistenceId 字段进行连接。连接是通过代理键完成的。 OvereserId 是一个整数。
  • @Vadim 如果引用被映射到 PersistenceId,那么一开始就不需要提供 PropertyRef。
猜你喜欢
  • 1970-01-01
  • 2010-12-08
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多