NHibernate的如何查询针对一个IList 属性?(NHibernate How do

2019-06-17 20:15发布

我想对查询一个IList <String>的属性上使用NHibernate我的领域类之一。 下面是一个简单的例子来说明:

public class Demo
{
    public Demo()
    {
        this.Tags = new List<string>();
    }
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<string> Tags { get; set; }
}

这样映射:

<class name="Demo">
<id name="Id" />
<property name="Name" />
<bag name="Tags">
  <key column="DemoId"/>
  <element column="Tag" type="String" />
</bag>

而我能够保存和检索就好了。 我们查询,其中标签属性包含一个指定的值我的域名类的实例:

var demos = this.session.CreateCriteria<Demo>()
            .CreateAlias("Tags", "t")
            .Add(Restrictions.Eq("t", "a"))
            .List<Demo>();

结果在误差:采集是不是关联:Demo.Tags

var demos = (from d in this.session.Linq<Demo>()
                     where d.Tags.Contains("a")
                     select d).ToList();

导致错误:Objct引用不设置为一个对象的一个​​实例。

var demos = this.session.CreateQuery("from Demo d where :t in elements(d.Tags)")
            .SetParameter("t", "a")
            .List<Demo>();

做工精细,但我真正的领域类有很多很多的属性,我建立一个复杂的动态查询,做丑陋的字符串操作是不是我的第一选择。 我宁愿使用的ICriteria或LINQ。 我有一个可以输入多种不同的可能的搜索条件的用户界面。 那现在建立起来的ICriteria的代码是几十排长。 我真的不想把它转换成HQL字符串操作。

Answer 1:

该标准API的限制,是因为,我决定把我的弯曲的领域类,以适应。

我创建了一个实体类的标签。 我甚至不能将其创建为一个值对象。 它必须具有自己的ID。

我现在觉得脏。 但是,能够构建一个动态查询,而不诉诸字符串操作对我来说比坚守到域更重要。



Answer 2:

作为记录在这里:

17.1.4.1。 别名和属性引用

我们可以用:

...
A collection key             {[aliasname].key}      ORGID as {coll.key}
The id of an collection      {[aliasname].id}       EMPID as {coll.id}
The element of an collection {[aliasname].element}  XID as {coll.element}
...

有在DOC一个小bug ...而不是".element"我们必须使用".elements"

var demos = this.session.CreateCriteria<Demo>()
        .CreateAlias("Tags", "t")

        // instead of this
        // .Add(Restrictions.Eq("t", "a"))

        // we can use the .elements keyword
        .Add(Restrictions.Eq("t.elements", "a"))

        .List<Demo>();


Answer 3:

您需要使用SubCriterias不是别名。 这应该工作:

var demos = this.session.CreateCriteria<Demo>()
            .CreateCriteria("Tags")
            .Add(Restrictions.Eq("Tag", "a"))
            .List<Demo>();


Answer 4:

HQL:

from Demo d where :val in elements(d.Tags)


Answer 5:

切换到一类在一个字符串是一个妥协。 使用替代的ICriteria HQL是另一回事。 还有第三个妥协然而...使用自定义的SQL。 尝试了这一点。

var demos = Session.CreateCriteria<Demo>()
    .Add(Expression.Sql(
        "EXISTS (SELECT 1 FROM [Tags] custom_sql_t WHERE custom_sql_t.[DemoId] = {alias}.[Id] AND custom_sql_t.[Tag] = ?)",
        "a",
        NHibernateUtil.String))
    .List<Demo>();

这导致follwing SQL通过NHibernate的2.1.2.4000产生...

exec sp_executesql N'SELECT this_.Id as Id2_0_, this_.Version as Version2_0_, this_.Name as Name2_0_ FROM Demo this_ WHERE EXISTS (SELECT 1 FROM [Tags] custom_sql_t WHERE custom_sql_t.[DemoId] = this_.[Id] AND custom_sql_t.[Tag] = @p0)',N'@p0 nvarchar(1)',@p0=N'a'

看到这个帖子的另一个例子......

NHibernate的-从值类型的集合(非实体)查询来解决选择N + 1



Answer 6:

这是可能通过创建一个单独的标准:

ICriteria demoCriteria = session.CreateCriteria<Demo>();
...
demoCriteria.Add(Restrictions...);
...
ICriteria tagCriteria = demoCriteria.CreateCriteria("Tags");
tagCriteria.Add(Restrictions.In("elements", new {"Tag1", "Tag2", ...}));

return demoCriteria.List<Demo>();


文章来源: NHibernate How do I query against an IList property?