如何进行查询以返回包含列表中所有 id 的对象
Posted
技术标签:
【中文标题】如何进行查询以返回包含列表中所有 id 的对象【英文标题】:How can I make a query that returns objects who contain all ids from list 【发布时间】:2015-10-29 10:51:49 【问题描述】:我有两个对象:配置文件和标签。每个配置文件可以包含多个标签。在我的搜索页面上,我可以选择多个标签进行搜索。现在我想要一个查询来获取具有所有选定标签的所有配置文件。
因此,如果我使用WhereRestrictionOn().IsIn()
,我会得到至少包含 1 个标签的配置文件,但我需要返回包含列表中所有标签的配置文件。
我还为每个选定的标签尝试了多个 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);
【问题讨论】:
你需要一个子查询。检查这个***.com/q/23772548/1679310 这看起来不错@RadimKöhler,但我在这行遇到问题:query.WithSubquery .WhereProperty(() => file.id) .In(subQueryForAttribute);我不确定在 WhereProperty 中放什么。对象结构有问题。 @RadimKöhler 我的映射与您链接我的示例几乎相同。我也可以在问题中添加它。 哇,那是完全不同的场景。这不是多对多 - 你有 “正确的映射” ...所以它应该很容易......如果你仍然认为你不能使用那个解决方案,我会尝试起草那... 我在答案中发布了我的查询。你能检查一下吗?谢谢! 【参考方案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);
【讨论】:
嗯,我还是有问题。它没有返回任何结果。我似乎在子查询的 Select 上得到了一个空异常。 您能分享一下您最近的尝试吗?调整问题 更新了相关子查询。 我在本地尝试过,用我的实体(以可行的方式替换你的)和更新的 foreach ......它应该可以工作 是的!我也弄清楚出了什么问题。非常感谢大家的帮助!以上是关于如何进行查询以返回包含列表中所有 id 的对象的主要内容,如果未能解决你的问题,请参考以下文章