0

에 널 (null)에 속성을 호출 할 수 있습니다엔티티 프레임 워크는이 같은 데이터베이스의 일부 개체를 선택하는 코드를 표현

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

문제는 측면에서 어떤 물체가 존재하지 않게되었을 때에,이 라인은 작동이 오는가 어떻게 , null

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

나를 위해이 코드가 실제로있는 동안이 충돌 할 수처럼 보이는 FirstOrDefault() 반환 save.So 나는이 경우 null 참조 예외를 얻을 것으로 기대 그래서. 줄을 변경하려고 시도했습니다.

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

그런 식으로 null이 될 수 있지만 표현식에서는 유효하지 않습니다.

코드가 실제로 실행되지 않지만 sql로 변환 되었기 때문에 예외가 발생하지 않는다는 것을 알고 있습니다.하지만 왜 이런 식으로 처리했는지, 다른 방법으로 처리 할 수없는 이유를 설명하고 있습니다.

+1

힌트는 코드가 실행되지 않는다는 것입니다. 값이 'null'이면 속성이 호출되지 않는 방식으로 SQL로 변환됩니다. – Enigmativity

+0

@Enigmativity 변환 된 것으로 알고 있지만 유효하지 않은 코드처럼 보이지만 유효한 것으로 보이는 코드는 허용되지 않습니다. – ColmanJ

+1

"다른 방향"을 지원하지 않으면 EF 오류가 아닙니다. 첫째, '?'연산자는 EF가 개발되었을 때 존재하지 않았습니다. 둘째로, 가장 중요한 점은, 연산자 '?'는 C# 표현식 트리에서 지원되지 않는다는 것입니다 (MS 개발자는 명확한 아이디어가 없으므로 어떤 유형의 (새로운) 표현식이 표현되어야하는지 결정하지 않았기 때문에) EF와 다른 표현 번역자는 아무 것도 할 수 없습니다. –

답변

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을 만들면됩니다.