nHibernate连接查询

时间:2011-02-22 13:03:01

标签: nhibernate join

我有两个表(图表表示 - 一个表是节点,另一个是节点之间的链接),我想在nHibernate中写这个查询:

SELECT 
  distinct(t.id),  t.NodeName, e.Fk_linkOne, e.Fk_linkTwo, e.RelationName
FROM Nodes t
INNER JOIN NodeRelation e ON t.Id=e.Fk_linkOne OR t.Id=e.Fk_linkTwo
where (e.Fk_linkOne =84 OR e.Fk_linkTwo=84 ) AND t.Id!=84

我没有找到如何通过连接连接两个表,其中包含OR ..

ICriteria criteriaSelect = Session
  .CreateCriteria(typeof(NodeRelation ), "nodeRelations")                  
  .CreateCriteria("nodeRelations.Node", "node",
       NHibernate.SqlCommand.JoinType.InnerJoin)

3 个答案:

答案 0 :(得分:0)

您只能根据在映射中定义的关联来定义连接。据我所知,你无法在Nhibernate中定义OR样式关系。考虑使用自引用样式图表示。

public class Node
{
    public IList<Node> Parents { get; set; }
    public IList<Node> Children { get; set; }
}

<bag name="Parents" table="Node_Relation">
   <key column="ChildId" />
   <many-to-many class="Node" column="ParentId" />
</bag>
<bag name="Children" table="Node_Relation">
   <key column="ParentId" />
   <many-to-many class="Node" column="ChildId" />
</bag>

答案 1 :(得分:0)

您应该使用DetachedCriteria来完成相同的操作。我不确定你的查询,但我会犹豫不决。

var dc1= DetachedCriteria.For(typeof( NodeRelation )).Add(Restrictions.Eq("Fk_linkOne", 84))
.SetProjection(Projections.Property("Fk_linkOne"));

var dc2= DetachedCriteria.For(typeof( NodeRelation )).Add(Restrictions.Eq("Fk_linkTwo", 84))
.SetProjection(Projections.Property("Fk_linkTwo"));

Session.CreateCriteria(typeof(Nodes))
.Add(Subqueries.PropertyIn("Id", dc1))
.Add(Subqueries.PropertyIn("Id", dc2))
.Add(Restrictions.Eq("Id", 84)).List<Nodes>;

希望上面的查询是正确的。请告诉我,如果你在尝试涂抹后不能让它工作,请告诉我你试过的。

答案 2 :(得分:0)

它总是取决于你的课程而不是你的课程。请记住,您正在使用ORM并且正在使用类模型。

假设您的课程如下:

class Node
{
  List<Node> Relations { get; private set; }
  List<Node> InverseRelations { get; private set; }
}

你可以这样映射:

<class name="Node">
<!-- .... -->
  <bag name="Relations" table="NodeRelation">
    <key name="Fk_linkOne">
    <many-to-many class="Node" column="Fk_linkTwo"/>
  </bag>
  <bag name="InverseRelations" table="NodeRelation" inverse="true">
    <key name="Fk_linkTwo">
    <many-to-many class="Node" column="Fk_linkOne"/>
  </bag>

</class>

这样你就得到了不对称关系(这意味着:当节点A与节点B相关时,B当然不一定与A相关,当然除了InverseRelation)。我不知道你真正需要什么,所以这是基于你的数据库设计的假设。

您的查询可能如下所示:

from Node n
where 
  :x in elements(n.Relations)
  or :x in elements(n.InverseRelations)

注意:x是实体类型,而不仅仅是id(您需要使用session.Load<Node>(84)加载它),

samy查询的另一种方式:

select distinct n
from Node n 
  inner join n.Relations e1 
  inner join n.InverseRelations e2
where e1.id = 84 or e2.id = 84

或者不使用反向关系的另一种方式:

select n
from Node n, Node n2 inner join n.Relations e
where
  (n = n2 and e.id = 84)
  OR (n = e and n2.id = 84)

在标准中,我会采用第二种解决方案,并按如下方式编写:

session.CreateCriteria<Node>("n")
  .SetProjection(Projections.Distinct("n"))
  .CreateCriteria("Relations", "e1")
  .CreateCriteria("InverseRelations", "e2")
  .Add(Expression.Or(
    Expression.Eq("e1.id", 84),
    Expression.Eq("e2.id", 84));