实体框架可以在表达式

时间:2017-11-06 11:34:00

标签: c# linq-to-sql entity-framework-6 nullreferenceexception linq-expressions

我有代码在数据库中选择一些对象,如下所示:

db.ObjectTypes.GroupJoin(db.Terms, t => t.Id, term => term.ObjectTypeId, (t, terms) => new Term()
{
    Type = t.Type,
    ObjectTypeId = t.Id,
    Deadline = ((int?)terms.FirstOrDefault().Deadline ?? 0),
});

问题是,当没有任何对象时,这条线是如何工作的,所以FirstOrDefault()会返回null

((int?)terms.FirstOrDefault().Deadline ?? 0)

对我来说,这段代码看起来可能会在它实际保存时崩溃。所以我希望在这种情况下得到一个空引用异常。我试图将行改为

(terms.FirstOrDefault()?.Deadline ?? 0)

这样你知道它可以为null,但这在表达式中不起作用。

我知道它有效并且没有例外,因为代码实际上并没有被执行但是已经转换为sql,但是我正在寻找解释为什么它这样做并且不可能在另一种方式?

1 个答案:

答案 0 :(得分:0)

嗯,就像提到的 Enigmativity 一样,代码将不会被执行。由于terms为空,因此不会进行分组,因此不会执行FirstOrDefault()

您可以在以下示例中看到它。 (只是一个简单的)

using System;
using System.Collections.Generic;
using System.Linq;

public class static Program {

    public static void Main() 
    {
        var terms = new List<Term>();

        var result = ((int?)terms.FirstOrDefault().Deadline ?? 0);        
        Console.WriteLine(result);

        var result2 = (terms.FirstOrDefault()?.Deadline ?? 0);
        Console.WriteLine(result2);
    }

    private class Term
    {
        public int Deadline { get; set; }
    }
}

上面的代码将被翻译成以下代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;

[assembly: AssemblyVersion("0.0.0.0")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[module: UnverifiableCode]
public class Program
{
    private class Term
    {
        [DebuggerBrowsable(DebuggerBrowsableState.Never), CompilerGenerated]
        private int <Deadline>k__BackingField;

        public int Deadline
        {
            [CompilerGenerated]
            get
            {
                return this.<Deadline>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.<Deadline>k__BackingField = value;
            }
        }
    }

    public static void Main()
    {
        List<C.Term> source = new List<C.Term>();
        int? num = new int?(source.FirstOrDefault<C.Term>().Deadline);
        int value = num.HasValue ? num.GetValueOrDefault() : 0;
        Console.WriteLine(value);

        // just added this line for more readability
        C.Term expr_3A = source.FirstOrDefault<C.Term>();
        int value2 = (expr_3A != null) ? expr_3A.Deadline : 0;
        Console.WriteLine(value2);
    }
}

您可以看到您提到的行(((int?)terms.FirstOrDefault().Deadline ?? 0))会产生NullReferenceException?.将避免例外。 您可以尝试here或只使用上面的示例代码创建Console Application