考虑这个代表层次结构中的节点的类:
public class Node
{
public Node()
{
Children = new List<Node>();
}
public virtual int Id { get; set; }
public virtual IList<Node> Children { get; set; }
public virtual Node Parent { get; set; }
public virtual int Position
{
get { return Parent == null ? -1 : Parent.Children.IndexOf(this); }
set { }
}
}
映射看起来像这样(由于 NHibernate 不支持双向关联中的列表,我在这里使用了一个包,让孩子们自动确定他们的位置):
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" namespace="AmbiguousColumn" assembly="AmbiguousColumn" xmlns="urn:nhibernate-mapping-2.2">
<class name="Node">
<id name="Id" type="Int32">
<generator class="identity" />
</id>
<bag name="Children" inverse="true" cascade="all" order-by="Position">
<key column="Parent" />
<one-to-many class="Node" />
</bag>
<many-to-one name="Parent" />
<property name="Position" />
</class>
</hibernate-mapping>
要加载所有节点及其子节点,我将使用如下查询:
var nodes = session.QueryOver<Node>()
.Fetch(x => x.Children).Eager
.List();
但是,执行此操作会导致异常:
NHibernate.Exceptions.GenericADOException:无法执行查询 [...(sql)...] ---> System.Data.SqlClient.SqlException:不明确的列名“位置”。
SQL:
SELECT
this_.Id as Id0_1_,
this_.Parent as Parent0_1_,
this_.Position as Position0_1_,
children2_.Parent as Parent3_,
children2_.Id as Id3_,
children2_.Id as Id0_0_,
children2_.Parent as Parent0_0_,
children2_.Position as Position0_0_
FROM
Node this_
left outer join
Node children2_
on this_.Id=children2_.Parent
ORDER BY
Position
我理解为什么会发生这种情况:NH 两次加入同一个表,但使用 order 子句而不限定列名。
问题是:我怎样才能使这种情况发挥作用?诉诸而不是可能很困难,因为我想建立双向关系。
SO上有几个类似的问题,但我没有找到实际的解决方案。
更新:错误是特定于数据库/驱动程序的。使用 Sql Server CE(例如 SqlServerCeDriver 和 MsSqlCe40Dialect)我得到了正确的查询。使用 Sql Server(例如 Sql2008ClientDriver 和 MsSql2012Dialect)会产生不合格的查询。
根据我自己的测试,这种行为在github上的master分支中依然存在。