代码之家  ›  专栏  ›  技术社区  ›  J. Perkins

如何使用NHibernate查询多对多集合?

  •  0
  • J. Perkins  · 技术社区  · 16 年前

    我有一个活动列表,每个活动都有一个参与者列表。以下是映射:

      <class name="Activity" lazy="false">
        <id name="ID">
          <generator class="guid" />
        </id>
        <list name="Participants">
          <key column="Activity" />
          <index column="Ord" />
          <many-to-many column="Contact" class="Model.Contact" />
        </list>
        <property name="Timestamp" />
      </class>
    
      <class name="Contact" lazy="false">
        <id name="ID">
          <generator class="guid" />
        </id>
        <property name="Name" />
      </class>
    

    var crit = ModelSession.Current.CreateCriteria<Activity>()
       .AddOrder(Order.Desc("Timestamp"))
       .SetFirstResult(start)
       .SetMaxResults(count);
    

    现在我只需要检索特定人员参与的那些活动,换句话说:where Contact.Name,比如“%some_Name%”。在原始SQL中,我可能会这样写:

    select * from Activity where ID in (select p.Activity from Participants p, 
    Contact c where p.Contact=c.ID and c.Name like '%some_name%')
    

    2 回复  |  直到 16 年前
        1
  •  3
  •   J. Perkins    14 年前

    上面的ChssPly76响应不太正确这是一种单向关系,因此项目联系人上没有“活动”属性,但它使我走上了正确的轨道。 正确的答案实际上要简单得多(在它自己的答案中,我可以正确地格式化它):

    crit.CreateCriteria("Participants")
       .Add(Expression.Like("Name", like));
    

    添加到原始问题的标准中,这表示“返回按时间戳排序的活动页面,其中参与者具有此名称”。

    更进一步说,我真的很想在参与者列表或活动描述中出现搜索词的任何活动。在这种情况下,您确实需要子查询。

    var subquery = DetachedCriteria.For<Activity>()
       .SetProjection(Projections.Property("ID"))
       .CreateCriteria("Participants")
       .Add(Expression.Like("Name", search_term));
    
    crit.Add(Expression.Or(
       Subqueries.PropertyIn("ID", subquery),
       Expression.Like("Description", search_term));
    
        2
  •  1
  •   ChssPly76    16 年前

    您只需在条件中添加适当的条件:

    crit.CreateAlias("Participants", "participant")
    .Add( Expression.Like("participant.Name", "%some_name%") );
    

    Criteria associations NHibernate文档的第章了解更多详细信息

    使现代化 DetachedCriteria 指定您的 参与者 作为子查询的条件:

    DetachedCriteria subquery = DetachedCriteria.For(typeof(Participant))
     .SetProjection(Projections.Property("activity"))
     .Add( Expression.Like("name", "%some_name%") );
    crit.add( Subqueries.GeAll("ID", subquery) ).List();