I am trying to query against an IList
public cl
As documented here:
we can use:
...
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}
...
there is a small bug in doc... instead of ".element"
we have to use ".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>();
You need to use SubCriterias not alias. This should work:
var demos = this.session.CreateCriteria<Demo>()
.CreateCriteria("Tags")
.Add(Restrictions.Eq("Tag", "a"))
.List<Demo>();
Switching to a class over a string is one compromise. Using HQL instead of ICriteria is another. There is a third compromise however... use custom SQL. Try this out.
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>();
This results in the follwing SQL being generated by 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'
See this post for another example...
NHibernate - Querying from a collection of Value Types (non-Entity) to solve Select N+1
This is possible by creating a separate criteria:
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>();
So because of limitations of the Criteria API, I decided to bend my domain classes to fit.
I created an entity class for the Tag. I couldn't even create it as a value object. It had to have its own id.
I feel dirty now. But being able to construct a dynamic query without resorting to string manipulation was more important to me than staying true to the domain.
HQL:
from Demo d where :val in elements(d.Tags)