3

.NET Dapper を使用して、整数値 (0/1) を含むデータベース フィールドを取得して、クラスの null 許容ブール型プロパティにマップする際に問題が発生しています。

物事を単純にするために、問題を再現するために必要な最低限のクラスにクラスを削除して名前を変更しました。

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 を削除して 1 日と呼ぶように見えるかもしれません。ただし、これが機能しない理由は、この同じクラスを使用して Web サービスとの間でレコードをシリアル化しているためであり、false と null の違いを識別できる必要があります。null 許容プロパティ型を持つクラスと持たないクラスの 2 つのクラスを持つことを考えましたが、1 つではなく 2 つのクラスを維持するという追加のオーバーヘッドがあります。

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

4

2 に答える 2

3

nullable bool/long などに関して、Dapper コードに問題があるようです。

ソース コードの 3 行を次に示します (バージョン 1.12.1.1 の 2375 ~ 2377 行)。問題は最初の行にあります:

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?) の後に null 許容の疑問符がなくなっていることに注意してください。

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

このコード行はエラーをスローしません。

したがって、解決策はソースの再コンパイルでした。この変更をプロジェクトに提出して、望ましくない副作用が発生するかどうかを確認してもらいます。

于 2013-06-06T23:05:03.503 に答える
0

Bit は 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();
于 2013-06-07T21:36:15.353 に答える