LINQ to SQL布尔值的评估顺序

时间:2013-12-17 22:08:45

标签: c# sql linq linq-to-sql

当我向PerformQuery方法提供null参数时,我有以下代码生成空引用异常。

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));
}

我确信TableObject不是空的。怎么可能呢?并且它的属性Hash不可为空,所以它也不应该为空(尽管我已经检查了null并没有改进)。

我已经通过在执行查询之前计算我正在搜索的Guid字符串来解决这个问题,但我很好奇为什么LINQ继续评估条件,即使obj为空。这是因为LINQ to SQL优化,布尔值的评估顺序不同于传统的if else语句吗?

2 个答案:

答案 0 :(得分:6)

在进入LINQ to SQL查询之前,应该评估本地对象。数据库无法知道您的对象是否为空。

 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));
    }

答案 1 :(得分:3)

这是因为linq-to-sql尝试将整个表达式转换为SQL。因此,在此转换期间会出现空对象引用。您可以判断,因为甚至没有SQL发送到数据库。

解决方案是在撰写查询之前评估obj.Guid(如在@ ps2goat的答案中,但原因略有不同)。