How to ignore convert to nullable in lambda expressions?
Asked Answered
I

3

5

I'm trying to build a parser of expressions to Odata, and i'm getting an error, when the field is nullable.

public class UserRight
{
    public bool? active
}

public void Test(){
    Expression<Func<UserRight, bool>> expression = p => p.Active == true;
}

It generates me the following expression:

{p => (p.Active == Convert(True, Nullable`1))}

But I'd like to receive it as

{p => (p.Active == True)}

In order to avoid this "Convert". Is there an easy way to do that? Because my parser is ready, and I would not like to rebuild it just because of a nullable field.

Imidazole answered 29/5, 2018 at 17:12 Comment(3)
p => p.Active == true is actually p => p.Active == (bool?)true. And the cast in expression trees is represented by Convert expression. So you cannot avoid it.Shellieshellproof
You say you're getting an error, what is the error? There may be a better way to solve your problem.Honea
I was doing some test in my PC, that expressions generates me {p => (p.active == Convert(True))}, "?? false" generates me {p => (p.active ?? False)} and ".Value" generates {p => (p.active.Value == True)}Lasky
C
4

No, there's no way to avoid it. The operator you're calling accepts a bool?, not a bool, and so the argument must be a bool?, else it couldn't compile. There is an implicit conversion from bool to bool?, and that's seen from the convert expression. Without that implicit conversion it wouldn't be a valid expression.

You could in theory manually construct your own expression that used a true nullable boolean constant value, but there's no way to make that lambda "automatically" generate such an expression, and trying to create that new expression is almost certainly way more work than simply having your query provider handle the convert expression.

Cognoscenti answered 29/5, 2018 at 17:19 Comment(8)
He is using "Active", which is bool?, but must use "Active.Value" if wants a bool. I think my answer below works.Lasky
@Lasky You're just changing what you're expecting their parser to be able to support from converting a convert expression into a conditional expression and two different property getters for different properties, and are also now demanding that anyone using this query provider not write an entirely reasonable query that one would expect the query provider to be able to handle, and must instead write something much more complicated every single time.Cognoscenti
But if he use p=> p.GetValueOrDefault() == true i think the parser must understand it. The problem here isn't the "true" is the p.Active, IMHO.Lasky
@Lasky Why must their query provider understand it? If you wanted to support both, I guess I could see that. It doesn't remove the OP's problem, it's just suggesting a new expression that they should also support.Cognoscenti
OP wants to avoid "true" as Convert(True, Nullable'1). This happens because p.Active is Nullable. But p.Active.Value it isn't and p.GetValueOrDefault() it isn't. If query provider understand p.Active, it should understand p.Active.Value. Even @Jonathan Santiago answer is good fot this.Lasky
@Lasky You've avoided a convert expression that the query provider doesn't know what to do with by putting in a method call that the query provider most likely doesn't know what to do with, and in addition to that you've now burdened all users of the query provider with the inability to write the expression that the OP wants them to be able to write.Cognoscenti
p.Active.Value isn't a method.Lasky
@Lasky No, it's a property, as I said. GetValueOrDefault is a method, as I said when referring to that.Cognoscenti
P
2

I honestly do not like Nullable in boolean attributes, more to suit your case:

Expression<Func<UserRight, bool>> expression = p => p.Active ?? false

This would consider the nulls as false, and would solve your case.

Penetrance answered 29/5, 2018 at 17:28 Comment(0)
L
0

When you are using nullable variable, you should check it if has value, and if it was true, so access the value. something like this:

p=> p.Active.HasValue ? p.Active.Value : false; //'== true' unnecessary

Or

p=> p.Active.GetValueOrDefault(); //the same but shorter.

I'm not sure how your parser works but i think this can work.

Lasky answered 29/5, 2018 at 17:18 Comment(2)
That actually works, but I would still have some problems. I'm using it to converto from expression, to OData expression. So now instead of generating "active eq true", it would generate "active.GetValueOrDefault eq true" I'm trying to find another way Thanks for the quick answer!Imidazole
@FernandoAugustoStavroDuarte look at Jonathan answer.Lasky

© 2022 - 2024 — McMap. All rights reserved.