我想对查询一个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字符串操作。
该标准API的限制,是因为,我决定把我的弯曲的领域类,以适应。
我创建了一个实体类的标签。 我甚至不能将其创建为一个值对象。 它必须具有自己的ID。
我现在觉得脏。 但是,能够构建一个动态查询,而不诉诸字符串操作对我来说比坚守到域更重要。
作为记录在这里:
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>();
您需要使用SubCriterias不是别名。 这应该工作:
var demos = this.session.CreateCriteria<Demo>()
.CreateCriteria("Tags")
.Add(Restrictions.Eq("Tag", "a"))
.List<Demo>();
HQL:
from Demo d where :val in elements(d.Tags)
切换到一类在一个字符串是一个妥协。 使用替代的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
这是可能通过创建一个单独的标准:
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>();