使用NHibernate查询字符串集合

时间:2009-03-17 15:04:22

标签: nhibernate hibernate

我有一个“Item”类,这个类有一个集合“Tags”。

Item
    IList<string> Tags;

我的数据库看起来像这样:

Items
   Id

Tags
   ItemId
   TagName

我正在尝试获取所有带有“x”和“y”标签的项目。我如何使用NHibernate(最好使用标准API)?它甚至可能吗?

感谢。

编辑: 我可以不映射Tag对象吗?它不具有1个查询。 像

这样的东西
  1. var q =将返回标记为x或标记为y的对象的所有id的查询。

  2. var res =将返回带有Id的所有项目的查询(q.Execute())

3 个答案:

答案 0 :(得分:2)

尝试这样的事情:

session.CreateCriteria(typeof(Item))
    .CreateCriteria("Tags", global::NHibernate.SqlCommand.JoinType.InnerJoin)
    .Add(Expression.Eq("TagName", "x"))
    .Add(Expression.Eq("TagName", "y"))
    .List()

编辑: 确保ItemTag之间存在双向关联。在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);

它似乎按预期工作。