.NET Dapper nullable 캐스트 오류

.net dapper nullable orm

문제

.NET Dapper를 사용하여 클래스의 nullable 부울 속성에 매핑 할 정수 값 (0/1)이 포함 된 데이터베이스 필드를 가져 오는 중에 문제가 발생했습니다.

일을 단순하게 유지하기 위해 나는 문제를 재현하는 데 필요한 최소한의 클래스로 이름을 바꾸었다.

public class Test
{
    public bool? TestField { get; set; }
}

다음 코드가 호출되어 Test 클래스를 채우는 경우 :

var Results = DBConnection.Query<Test>("SELECT 0 As TestField]").ToList();

다음과 같은 오류가 발생합니다.

Invalid cast from 'System.Int32' to 'System.Nullable`1[[System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

물음표를 제거하여 필드를 null이 아닌 부울 (예 : public bool TestField)로 만들면 모든 것이 잘 동작합니다.

즉각적인 대답은 nullable을 제거하고 하루라고 부를 수 있습니다. 그러나 작동하지 않는 이유는이 클래스를 사용하여 웹 서비스와주고받는 레코드를 직렬화하기 때문이며 우리는 false와 null의 차이점을 알 수 있어야합니다. Nullable 속성 유형이있는 클래스와없는 클래스가 두 개 있다고 생각했지만 하나가 아닌 두 클래스를 유지 관리하는 오버 헤드가 추가되었습니다.

속성 집합 중 사용자 지정 데이터 변환이 이상적입니다. 비록 이것이 가능하다는 것을 암시하는 훌륭한 문서에서 아무것도 발견하지 못했습니다.

수락 된 답변

nullable bool / long 등과 관련하여 Dapper 코드에 문제가있는 것 같습니다.

다음은 소스 코드의 세 줄입니다 (줄 2375-2377 버전 1.12.1.1). 문제는 첫 번째 줄에 있습니다.

il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [target][target][value][member-type-token]
il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); // stack is now [target][target][value][member-type]
il.EmitCall(OpCodes.Call, typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(Type) }), null); // stack is now [target][target][boxed-member-type-value]

이 코드가 출력되면 다음 코드 행과 동일 해집니다.

Convert.ChangeType(0, typeof(bool?));

불행히도, 이것은 내가보고있는 오류를 던졌습니다. 위의 첫 번째 il.Emit () 행을 다음과 같이 변경하십시오.

il.Emit(OpCodes.Ldtoken, nullUnderlyingType ?? memberType); // stack is now [target][target][value][member-type-token]

생성 된 동등한 코드 행은 다음과 같습니다. 끝에 typeof (bool?) 끝에 더 이상 nullable 물음표가 없습니다.

Convert.ChangeType(0, typeof(bool));

이 코드 행은 오류를 발생시키지 않습니다.

그래서 해결책은 소스의 재 컴파일이었습니다. 이것이 원하지 않는 부작용을 일으키는 지 검토하기 위해이 변경 사항을 다시 프로젝트에 제출할 것입니다.


인기 답변

비트는 bool에 멋지게 매핑되어야합니다.

create table Test
(
    TestField bit null
)

또 다른 옵션은 다음과 같이하는 것입니다.

var Results = DBConnection.Query<Test>("SELECT cast(case TestField when 1 then 1 when 0 then 0 else null end as bit)  As TestField from Test").ToList();


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