简体   繁体   English

在Linq-To-Sql中避免“Nullable对象必须有值。”

[英]Avoid “Nullable object must have a value.” in Linq-To-Sql

I have a method query like this: 我有这样的方法查询:

public IList<BusinessObject> GetBusinessObject(Guid? filterId)
{
    using (var db = new L2SDataContext())
    {
        var result = from bo in db.BusinessObjects
                     where (filterId.HasValue)
                               ? bo.Filter == filterId.value
                               : true
                     orderby bo.Name
                     select SqlModelConverters.ConvertBusinessObject(bo);
        return result.ToList();
    }
}

At runtime, this throws a System.InvalidOperationException: Nullable object must have a value. 在运行时,这会抛出System.InvalidOperationException: Nullable object must have a value.

Looking at the Debugger, the problem is my Where Clause: Linq To SQL tries to convert the entire thing to SQL, so even if filterId is NULL, it will still try to access filterId.value. 查看调试器,问题是我的Where子句:Linq To SQL尝试将整个事物转换为SQL,因此即使filterId为NULL,它仍将尝试访问filterId.value。

I thought/hoped the C# compiler/CLR would evaluate that where clause as a code block and only send one of the two branches to Linq To SQL, but that's not how it works. 我认为/希望C#编译器/ CLR将where子句作为代码块进行评估,并且只将两个分支中的一个发送到Linq To SQL,但这不是它的工作原理。

My refactored version works, but is not very elegant: 我的重构版本有效,但不是很优雅:

public IList<BusinessObject> GetBusinessObject(Guid? filterId)
{
    using (var db = new L2SDataContext())
    {
        var temp = from bo in db.BusinessObjects select bo;
        if(filterId.HasValue) temp = temp.Where(t => t.Filter == filterId.Value);
        var result = from t in temp
                     orderby t.Name
                     select SqlModelConverters.ConvertBusinessObject(bo);
        return result.ToList();
    }
}

I know that Lazy-Evaluation will make sure that only one query is really sent, but having that temp object in there isn't that great really. 我知道Lazy-Evaluation将确保只发送一个查询,但在那里拥有那个临时对象并不是那么好。

你试过了吗:

where filterId == null || t.Filter == filterId

Your fix is exactly correct. 你的修复完全正确。 You are effectively trying to build up a query dynamically, based on your function input. 您正在有效地尝试根据您的函数输入动态构建查询。 It's a good idea to omit the where clause instead of supplying WHERE TRUE anyway. 省略where子句而不是提供WHERE TRUE是个好主意。 If I were writing this query, I would go with your fixed version myself. 如果我正在编写此查询,我会自己使用您的固定版本。

It's not as pretty as using the language keywords, but it's still the right way to approach the query in my opinion. 它不像使用语言关键字那么漂亮,但在我看来,它仍然是处理查询的正确方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM