DapperでDateTimeをUTCとして取得

.net c# dapper orm utc

質問

Dapperを使用してエンティティをSQL Server CEにマップしています。私がKind=UtcDateTimeを保存すると、それを読み返すと、 Kind=Unspecified DateTimeが得られ、これはあらゆる種類の問題につながります。

例:

var f = new Foo { Id = 42, ModificationDate = DateTime.UtcNow };
Console.WriteLine("{0} ({1})", f.ModificationDate, f.ModificationDate.Kind);
connection.Execute("insert into Foo(Id, ModificationDate) values(@Id, @ModificationDate)", f);
var f2 = connection.Query<Foo>("select * from Foo where Id = @Id", f).Single();
Console.WriteLine("{0} ({1})", f2.ModificationDate, f2.ModificationDate.Kind);

このコードは、次のように出力します。

20/09/2012 10:04:16 (Utc)
20/09/2012 10:04:16 (Unspecified)

私は、 DateTimeOffsetを使用する必要があることを知っていますが、残念ながらSQL CEではこのタイプのサポートがありません。

回避策はありますか? Dapperにすべての日付にDateTimeKind.Utcがあると仮定するように指示できますか?さらに一般的には、マッピングをカスタマイズするためのオプションは何ですか?


編集:私の現在の回避策は、Dapperが結果を具体化した後の日付をパッチすることですが、それはにおいの種類...

var results = _connection.Query<Foo>(sql, param).Select(PatchDate);

...

static Foo PatchDate(Foo f)
{
    if (f.ModificationDate.Kind == DateTimeKind.Unspecified)
        f.ModificationDate = DateTime.SpecifyKind(f.ModificationDate, DateTimeKind.Utc);
    return f;
}

受け入れられた回答

簡単な修正を求めている他の人のためにこの答えを追加する。これは、DapperのSqlMapper.TypeHandlerを追加することで可能になりました。

このクラスを追加して、dbの値をUTCとして指定された種類のdatetimeに変換します。

public class DateTimeHandler : SqlMapper.TypeHandler<DateTime>
{
    public override void SetValue(IDbDataParameter parameter, DateTime value)
    {
        parameter.Value = value;
    }

    public override DateTime Parse(object value)
    {
        return DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc);
    }
}

次に、私のWeb APIのGlobal.asaxファイルで、型ハンドラをdapperに追加します。

SqlMapper.AddTypeHandler(new DateTimeHandler());

常に日付をUTCとして挿入する必要がある場合は、SetValueメソッドで次のものを使用できます。

parameter.Value = DateTime.SpecifyKind(value, DateTimeKind.Utc);

人気のある回答

Dapperコードを調べました。私がdatetime(DbType.DateTimeにマップされている)のような値の型のために古いものでない限り、dapperはIDataReaderオブジェクトからの単純なキャストを行います。

擬似:yield return(DateTime)IDataReader.GetValue(0);

これは、汎用コードとラムダのうちDatetimeの特定のケースです。

AFAIK、SQL datetimeはoffset / timezoneを保存しないので、格納してフェッチする日時には種別は常に "Unspecified"と表示されます。

だから、それをきれいにするため 、あなたは大胆な内部に触れることができます:

これは大きなIL生成メソッド(DataRow Deserializer)に触れ、DateTimeのifの場合を入れなければならないので苦痛です。

または

UTCが問題になっているDateTimeの小道具にセッターを置くだけです(これはPOCOとちょっと違いますが、比較的穏やかです)。

class Foo
{
    private DateTime _modificationDate;
    public DateTime ModificationDate
    {
        get { return _modificationDate; }
        set { _modificationDate = DateTime.SpecifyKind(value, DateTimeKind.Utc); }
    }
    //Ifs optional? since it's always going to be a UTC date, and any DB call will return unspecified anyways
}


ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ