我有一个“Item”类,这个类有一个集合“Tags”。
Item
IList<string> Tags;
我的数据库看起来像这样:
Items
Id
Tags
ItemId
TagName
我正在尝试获取所有带有“x”和“y”标签的项目。我如何使用NHibernate(最好使用标准API)?它甚至可能吗?
感谢。
编辑: 我可以不映射Tag对象吗?它不具有1个查询。 像
这样的东西var q =将返回标记为x或标记为y的对象的所有id的查询。
var res =将返回带有Id的所有项目的查询(q.Execute())
答案 0 :(得分:2)
尝试这样的事情:
session.CreateCriteria(typeof(Item))
.CreateCriteria("Tags", global::NHibernate.SqlCommand.JoinType.InnerJoin)
.Add(Expression.Eq("TagName", "x"))
.Add(Expression.Eq("TagName", "y"))
.List()
编辑:
确保Item
和Tag
之间存在双向关联。在Fluent中,这看起来像是:
public class ItemMap : ClassMap<Item>
{
public ItemMap()
{
...
HasMany(x => x.Tags).Inverse();
...
}
}
public class TagMap : ClassMap<Tag>
{
public TagMap()
{
...
References<Item>(x => x.Item);
...
}
}
答案 1 :(得分:2)
我最近遇到了同样的问题,并且在我的特定问题的任何地方都没有找到一个好的解决方案。在我的解决方案中,我需要一个映射的Tags对象,因为它有点复杂。我将描述我做了什么,以防它帮助任何人。基本上这相当于以下sql:
SELECT *
FROM Items I
WHERE 2 = (
SELECT COUNT(DISTINCT TagName)
FROM Tags T
WHERE T.ItemId = I.ID)
AND (T.TagName = 'X' OR T.TagName = 'Y')
)
NHibernate.ICriteria criteria = session.CreateCriteria(typeof(Item),"I");
ICriterion tagCriteria = null;
foreach (string tag in tagNames) {
ICriterion newCriteria = Expression.Eq("TagName", tag);
if (tagCriteria == null) {
tagCriteria = newCriteria;
} else {
tagCriteria = Expression.Or(tagCriteria, newCriteria);
}
}
if (tagCriteria != null) {
DetachedCriteria subCriteria = DetachedCriteria.For<Tags>("T");
subCriteria.SetProjection(Projections.CountDistinct("TagName"))
.Add(Expression.EqProperty("I.Id", "T.ItemId"))
.Add(tagCriteria);
criteria = criteria.Add(Subqueries.Eq(tagNames.Count,subCriteria ));
}
return criteria.List<Item>();
答案 2 :(得分:1)
我认为您获得的问题与此相关:https://www.hibernate.org/117.html#A2 - 即使用条件API无法以这种方式查询字符串/组件的集合。
我使用HQL解决了这个问题,如链接常见问题解答中所述:
session.CreateQuery("from Item item "
+ "where :x in elements(item.Tags) and :y in elements(item.Tags)")
.SetString("x", X)
.SetString("y", Y);
它似乎按预期工作。