Dapper는 SingleOrDefault (DATEDIFF (...))에 대해 null을 반환합니다.

asp.net-mvc-3 dapper sql-server-2008

문제

다음과 유사한 SQL 문이 있습니다.

SELECT DATEDIFF(Day, startDate, endDate) FROM Data WHERE ProjectId=@id

DataProjectId 레코드가없는 경우 SQL Server는 null을 반환합니다.

Dapper에서는 다음을 통해이를 실행합니다.

value = conn.Query<int>("...").SingleOrDefault()

이 경우 SingleOrDefault 의미가 "this가 null이면 0을 반환합니다." 사실, 제 코드는 더 친숙하지 않습니다.

int toReturn = 0;
using (var conn = ...) {
  toReturn = conn.Query<int>("SELECT DATEDIFF(...))");
}
return toReturn;

내가이 코드를 디버깅하고 단계를 밟을 때, line yield return (T)func(reader) 가 널 포인터 예외를 던지고 있음을 발견했다.

내가 여기서 뭔가 잘못하고있는 것입니까, 아니면 설계 상입니까?

(FYI, 해결 방법은 ISNULL(..., 0) 내 선택을 래핑하는 것입니다.)

수락 된 답변

Data에 ProjectId의 레코드가없는 경우 SQL Server는 null을 반환합니다.

Data 일치하는 레코드가없는 경우 SQL 서버는 실제로 null을 반환하지 않습니다. 행을 반환하지 않습니다. 이 시나리오는 잘 작동합니다.

var result = connection.Query<int>( // case with rows
 "select DATEDIFF(day, GETUTCDATE(), @date)", new { date = DateTime.UtcNow.AddDays(20) })
 .SingleOrDefault();
result.IsEqualTo(20);

result = connection.Query<int>( // case without rows
    "select DATEDIFF(day, GETUTCDATE(), @date) where 1 = 0", new { date = DateTime.UtcNow.AddDays(20) })
    .SingleOrDefault();
result.IsEqualTo(0); // zero rows; default of int over zero rows is zero

둘 다 잘 작동합니다. ISNULL "수정하다"라고 말한 사실은 당신이 다른 시나리오에 대해 말하고 있다는 것을 의미합니다 - "나는 행을 반환했습니다"시나리오. 그 이후로, 당신의 코드가 말하는 것은 "널을 포함하고있는이 1 또는 그 이상의 정수를 가져 와서 null이 아닌 int로 매핑한다"이다. 그것은 가능하지 않으며 , 매퍼는 던져 넣기에 옳다. 예외. 대신, 당신이 원하는 것은 :

int? result = connection.Query<int?>(...).SingleOrDefault();

이제 행이 있으면 값을 int? 매핑하고 int? 그런 다음 단일 또는 기본값 적용합니다. 원하는 int로, 어쩌면 :

int result = connection.Query<int?>(...).SingleOrDefault() ?? 0;

"0 행"과 "null 결과"의 차이를 말할 수 있어야한다면 다음과 같이 제안합니다.

class NameMe {
    public int? Value {get;set;}
}
var row = connection.Query<NameMe>("select ... as [Value] ...", ...)
                    .SingleOrDefault();
if(row == null) {
   // no rows
} else if(row.Value == null) {
   // one row, null value
} else {
   // one row, non-null value
}

또는 비슷한



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow