Dapper로 DateTime을 UTC로 가져 오기

.net c# dapper orm utc

문제

Dapper를 사용하여 내 엔티티를 SQL Server CE에 매핑합니다. Kind=UtcDateTime 을 저장하면 다시 읽으면 Kind=UnspecifiedDateTimeKind=Utc 모든 종류의 문제가 발생합니다.

예:

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 객체에서 간단한 캐스트를 수행합니다.

Pseudo : yield return (DateTime) IDataReader.GetValue (0);

이것은 일반적인 코드와 람다 중에서 Datetime에 대한 특별한 경우입니다.

AFAIK, SQL datetime은 offset / timezone을 저장하지 않으므로 저장하고 가져 오는 날짜 / 시간에 항상 종류가 "지정되지 않음"으로 표시됩니다.

그래서, 그것을 깨끗하게 하기 위해, 당신은 더러운 내부를 만질 수 있습니다 :

이것은 큰 일리노이 생성 메서드 (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
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow