Как мне выразить «не в», используя лямбды? - PullRequest
7 голосов
/ 03 сентября 2010

Я пытаюсь создать предложение not in с помощью API NHibernate Criteria, используя NHLambdaExtensions.Читая документацию, я смог реализовать предложение in, выполнив

.Add(SqlExpression.In<Zone>(z => zoneAlias.ZoneId, new int[] { 1008, 1010 }))

Однако, когда я обертываю его вокруг SqlExpression.Not, я получаю сообщение об ошибке

Error   5   The best overloaded method match for 'NHibernate.LambdaExtensions.SqlExpression.Not<oms_dal.Models.Zone>(System.Linq.Expressions.Expression<System.Func<oms_dal.Models.Zone,bool>>)' has some invalid arguments
Error   6   Argument '1': cannot convert from 'NHibernate.Criterion.ICriterion' to 'System.Linq.Expressions.Expression<System.Func<oms_dal.Models.Zone,bool>>'

Яиспользуя этот фрагмент кода

.Add(SqlExpression.Not<Zone>(SqlExpression.In<Zone>(x => zoneAlias.ZoneId, new int[] { 1008, 1010 })))

Как мне это сделать?Используя обычный Criteria API, я смог сделать это

.Add(Restrictions.Not(Restrictions.In("z.ZoneId", new[] { 1008, 1010 })))

Ответы [ 2 ]

2 голосов
/ 23 декабря 2010

Использование старого мира с лямбдами, кажется, работает:

.Add(Expression.Not(SqlExpression.In<Zone>(z => zoneAlias.ZoneId, new int[] { 1008, 1010 }));
1 голос
/ 03 сентября 2010

Непосредственно не работал с критерием (я обычно использую Linq2NH), но, похоже, он не просто хочет логическую лямбду, поэтому вы не можете дать ей другой критерий.Это может сработать, хотя я видел, что у NH проблемы с членами массива в лямбдах:

.Add(SqlExpression.Not<Zone>(z=>new[]{1008,1010}.Contains(z.ZoneId))

EDIT: crap.Здесь происходит то, что инфраструктура на самом деле не использует лямбду, поэтому, пока она компилируется, она никогда не вызывает ее в процессе выполнения запроса.Вместо этого он рефлекторно исследует MSIL вашего делегата, производит обратный инжиниринг лямбда-выражения и преобразует его в строку для команды SQL.Это, очевидно, довольно сложный процесс, который дизайнеры пытаются упростить, попросив вас указать подсказки о том, что вы делаете (в данном случае тип объявленного вами SqlExpression), и искать шаблоны для идентификации процесса.В этом случае, тем не менее, даже учитывая подсказки, каркас не имеет ни малейшего представления о том, что вы пытаетесь сделать.

Если переводчик, стоящий за оценкой предложений Not (), не может определить цель логических циклов или вызовов методов,Вы, возможно, застряли с

.Add(SqlExpression.Not<Zone>(z=>z.ZoneId == 1008
                                || z.ZoneId == 1010))

Боже мой, я знаю, что для корректной работы Linq2NHibernate мне пришлось сваривать выражения таким образом.

...