.NET Dapperのnull可能なキャストエラー

.net dapper nullable orm

質問

.NET Dapperを使用すると、クラス内のnull可能なブール値プロパティにマップする整数値(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値ではないブール値(つまり、パブリックbool TestField)にすると、すべて正常に動作します。

即時の答えはnull可能性を取り除いて、それを1日と呼びます。しかし、この同じクラスを使用してWebサービスとの間でレコードをシリアライズするため、falseとnullの違いを伝える必要があるため、動作しない理由があります。私は2つのクラスを持つと思った.1つはヌル可能なプロパティ型で、もう1つはクラスなしであったが、1つではなく2つのクラスを維持するというオーバーヘッドが増えた。

プロパティセット中のカスタムデータ変換が理想的です。しかし、私はこれが可能であることを示唆するために、大まかなドキュメントで何も見つけられませんでした。

受け入れられた回答

Dapperコードにnull値のbool / longなどの問題があるように見えます。

ここにソースコードからの3行があります(行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
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ