如何创建一个返回包含列表中所有ID的对象的查询

时间:2015-10-29 10:51:49

标签: list nhibernate hql where queryover

我有两个对象:个人资料和标签。每个配置文件可以包含多个标记在我的搜索页面上,我可以选择多个要搜索的标签。现在,我想要一个查询,以获取包含所有选定标签的所有配置文件。

因此,如果我使用WhereRestrictionOn().IsIn(),我会获得包含至少一个标签的配置文件,但我需要返回包含列表中所有标签的配置文件。

我还为每个选定的标签尝试了多个Where条件,但之后我根本没有得到任何结果。

我不知道如何做到这一点任何帮助都非常感谢!

  

结构:

     

个人资料:Id

     

ProfileTag:ProfileId,TagId

     

标签:Id

映射配置文件

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Agrolink.Application.Models" assembly="Agrolink.Application">
  <class name="Agrolink.Application.Models.Profile" lazy="false" table="Profiles" >

    <id name="Id" column="Id"  >
      <generator class="identity" />
    </id>

    <bag name="Tags" table="ProfileTags" cascade="all-delete-orphan" inverse="true">
      <key column="IdProfile" not-null="true"/>
      <one-to-many class="Agrolink.Application.Models.ProfileTag"  />
    </bag>

  </class>
</hibernate-mapping>

映射ProfileTag

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Agrolink.Application.Models" assembly="Agrolink.Application">
  <class name="Agrolink.Application.Models.ProfileTag" lazy="false" table="ProfileTags" >

    <id name="Id" column="Id"  >
      <generator class="identity" />
    </id>

    <many-to-one name="Profile" class="Agrolink.Application.Models.Profile" column="IdProfile" cascade="save-update" />
    <many-to-one name="Tag" class="Agrolink.Application.Models.Tag" column="IdTag" cascade="none" />

  </class>
</hibernate-mapping>

映射标记

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Agrolink.Application.Models" assembly="Agrolink.Application">
  <class name="Agrolink.Application.Models.Tag" lazy="false" table="Tags" >

    <id name="Id" column="Id"  >
      <generator class="identity" />
    </id>

    <property name="Name" column="Name" />
    <property name="Type"  type="Agrolink.Application.Models.TagType, Agrolink.Application"  column="IdType" />

    <many-to-one name="Parent" class="Agrolink.Application.Models.Tag" column="IdParent" cascade="none" />

    <bag name="Children" table="Tags" cascade="all" inverse="true">
      <key column="IdParent" not-null="true"/>
      <one-to-many class="Agrolink.Application.Models.Tag"  />
    </bag>

  </class>
</hibernate-mapping>

SubQuery实现此目标(解决方案):

        Profile p = null;
        Account a = null;
        Institute i = null;

        var q = Session.QueryOver(() => p)
            .JoinAlias(x => x.Account, () => a)
            .JoinAlias(x => x.Institute, () => i)
            .Where(x => x.Type == ProfileType.Expert && x.Status == ProfileStatus.Active);

        if(_keywordIds.Any())
            foreach (var keywordId in _keywordIds)
            {
                Tag t = null;

                var subQ = QueryOver.Of<ProfileTag>()
                    .JoinAlias(pt => pt.Tag, () => t)
                    .Where(() => t.Id == keywordId)
                    .Select(pt => pt.Profile.Id);           

                q.WithSubquery.WhereProperty(() => p.Id).In(subQ);
            }

        if (_institute != null) q.Where(() => i.Id == _institute);

        if (!string.IsNullOrEmpty(_name)) q.Where(Restrictions.Disjunction()
                    .Add(Restrictions.Like("a.FirstName", _name + "%"))
                    .Add(Restrictions.Like("a.LastName", _name + "%"))
                );

        return (PagedList<Profile>) q.List<Profile>().ToPagedList(_page, _itemsPerPage);

1 个答案:

答案 0 :(得分:1)

几乎是这样,但我们需要所谓的Detached QueryOver,我们将使用构造QueryOver.Of

foreach (var keywordId in _keywordIds)
{
    //Tag t = null;

    var subQ = QueryOver.Of<ProfileTag>()
        //.JoinAlias(pt => pt.Tag, () => t)
        //.Where(() => t.Id == keywordId)
        .Where(x => x.Tag.Id == keywordId)
        //.Select(pt => t.Id);           
        .Select(pt => pt.Profile.Id);          

    q.WithSubquery.WhereProperty(() => p.Id).In(subQ);
}