Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ to SQL Order of Evaluation of a Boolean

I have the following code which generates a null reference exception when I provide a null argument to the PerformQuery method.

public class MyObject
{
    public Guid Guid { get; private set; }
}
public class TableObject
{
    // This is a Guid stored as a string
    public string Hash { get; set; }
}
public DataContext context;
public TableObject PerformQuery(MyObject obj)
{
    return context.TableObjects.FirstOrDefault(tableObject =>
        obj != null &&
            // Why is this side of the condition being evaluated if obj is null?
        string.Equals(obj.Guid.ToString(), tableObject.Hash));
}

I'm sure that the TableObject is not null. How could it? and It's property Hash is not nullable, so it shouldn't be null either (though I've checked both for null with no improvement).

I have solved the issue myself by calculating the Guid string that I am searching fore before executing the query, but I'm curious as to why LINQ continues to evaluate the conditional even if obj is null. Is this because of LINQ to SQL optimizations that the booleans are not evaluated in the same order as if it was a traditional if else statement?

like image 949
nock Avatar asked Dec 19 '25 19:12

nock


2 Answers

You should evaluate local objects before entering the LINQ to SQL query. The database has no way to know if your object is null.

 public TableObject PerformQuery(MyObject obj) {
        if (obj == null) {return null;}

        // also pull this out of the LINQ logic.
        string objGuid = obj.Guid.ToString();

        return context.TableObjects.FirstOrDefault(tableObject => 
            string.Equals(objGuid, tableObject.Hash));
    }
like image 127
ps2goat Avatar answered Dec 22 '25 09:12

ps2goat


This is because linq-to-sql tries to translate the whole expression into SQL. So the null object reference occurs during this translation. You can tell because no SQL is even sent to the database.

The solution is to evaluate obj.Guid before you compose the query (as in @ps2goat's answer, but the reason is slightly different).

like image 29
Gert Arnold Avatar answered Dec 22 '25 09:12

Gert Arnold



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!