Вы можете сделать это, но изменение модели предметной области, чтобы обойти ограничение NHibernate, болезненно для души.Можно запрашивать коллекции значений с помощью HQL, но ICriteria действительно удобна для построения запросов с логикой.Единственный способ, которым я знаю, как запрашивать коллекции значений с использованием ICriteria, - это пользовательский SQL.Это также болезненно и привязывает ваш код к вашей базе данных (!), Но для меня это меньшее из трех зол.Мое обоснование заключается в том, что ICriteria в конечном итоге разрешит такого рода запросы, и боль может быть устранена позже.
Хитрость заключается в том, чтобы использовать подзапрос в пользовательском SQL, чтобы было возможно объединение с таблицей сбора.Использование псевдонима таблицы, который не наступает на псевдонимы NHibernate, также является хорошей идеей (в данном случае custom_sql_t_v).И обратите внимание на {псевдоним} и?заполнители, из которых NHibernate будет заменен.
Вот пример, основанный на предположении, что ваш класс Tweet сопоставлен примерно так ...
<class name="Tweet" table="Tweet">
<id name="Id" unsaved-value="0">
<generator class="identity"/>
</id>
<version name="Version" unsaved-value="0"/>
<property name="UserName"/>
<property name="Message"/>
<set name="Votes" table="Tweet_Votes">
<key column="Tweet"/>
<element type="Int64" column="Vote"/>
</set>
</class>
Вот модифицированный запрос с использованием T-SQL (т.е.Microsoft SQL Server) ...
IList<TweetReport> tweets = Session.CreateCriteria<Tweet>()
.SetProjection(Projections.ProjectionList()
.Add(Projections.Id(), "Id")
.Add(Projections.Property("UserName"), "UserName")
.Add(Projections.Property("Message"), "Message")
.Add(Projections.Conditional(
Expression.Sql(
"EXISTS (SELECT 1 FROM [Tweet_Votes] custom_sql_t_v WHERE custom_sql_t_v.[Tweet] = {alias}.[Id] AND custom_sql_t_v.[Vote] = ?)",
userId,
NHibernateUtil.Int64),
Projections.Constant(true),
Projections.Constant(false)), "DidVote"))
.SetResultTransformer(Transformers.AliasToBean<TweetReport>())
.List<TweetReport>();
Окончательный SQL, сгенерированный NHibernate (я использовал NHibernate 2.1.2.4000), выглядит следующим образом ...
exec sp_executesql N'SELECT this_.Id as y0_, this_.UserName as y1_, this_.Message as y2_, (case when EXISTS (SELECT 1 FROM [Tweet_Votes] custom_sql_t_v WHERE custom_sql_t_v.[Tweet] = this_.[Id] AND custom_sql_t_v.[Vote] = @p0) then @p1 else @p2 end) as y3_ FROM Tweet this_',N'@p0 bigint,@p1 char(1),@p2 char(1)',@p0=123,@p1='Y',@p2='N'
Преимущество всего этогов том, что делать LIKE с коллекцией строк возможно - то, чего я не думаю, можно сделать с помощью HQL.