How do I express “not in” using lambdas?

I'm trying to create a not in clause with the NHibernate Criteria API using NHLambdaExtensions. Reading the documentation I was able to implement the in clause by doing

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

However, when I wrap it around SqlExpression.Not I get the error

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>>'

I'm using this piece of code

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

How can I accomplish this? Using the regular Criteria API I was able to do this

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

Haven't worked with criterion directly (I generally use Linq2NH), but it looks like Not simply wants a boolean lambda, so you can't give it another criterion. This may work, though I've seen NH have trouble with array members in lambdas:

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

EDIT: crap. What's going on here is that the framework is not actually using the lambda, so while this compiles, the framework never actually calls it in the process of running the query. It is instead reflectively examining the MSIL of your delegate, reverse-engineering your lambda expression and converting that to a string for the SQL command. That is, obviously, a rather complex process that the designers try to simplify by having you specify hints about what you're doing (in this case the type of SqlExpression you declared) and looking for patterns to identify the process. In this case, though, even given the hints, the framework has no clue what you're trying to do.

If the translator behind evaluating Not() clauses cannot divine the purpose of logic loops or method calls, you may well be stuck with

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

Goodness knows I've had to boil down expressions this way for Linq2NHibernate to work correctly.


与lambda一起使用旧世界似乎有效:

.Add(Expression.Not(SqlExpression.In<Zone>(z => zoneAlias.ZoneId, new int[] { 1008, 1010 }));
链接地址: http://www.djcxy.com/p/2580.html

上一篇: 为什么使用字符串标识符来访问资源数据?

下一篇: 我如何表达“不在”使用lambdas?