Dapper로 DateTime을 UTC로 가져 오기
Dapper를 사용하여 엔터티를 SQL Server CE에 매핑하고 있습니다. 다른 이름으로 저장 나는 경우 DateTime
에 Kind=Utc
그것을 다시 내가 읽을 때, 나는 얻을 DateTime
로 Kind=Unspecified
, 어떤 문제의 모든 종류의 리드.
예:
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은 오프셋 / 시간대를 저장하지 않으므로 저장하고 가져 오는 모든 날짜 시간에 종류가 항상 "Unspecified"라고 표시됩니다.
따라서 깔끔하게 수행 하려면 깔끔한 내부를 만질 수 있습니다.
큰 IL 생성 방법 (DataRow Deserializer)을 만지고 DateTime의 경우 if 케이스에 넣어야하므로 고통 스럽습니다.
또는
UTC가 문제인 DateTime props에 setter를 넣으면됩니다 (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
}
위의 @ matt-jenkins 답변을 기반으로 DateTimeOffset
/ DateTimeOffset?
필드 / 속성을 MySQL 5.7 데이터베이스 (지원하지 않음 DbType.DateTimeOffset
) 와 원활하게 통합하기 위해 여기에 전체 솔루션을 넣고 싶었습니다 .
public static class DapperExtensions
{
class DateTimeOffsetTypeHandler : SqlMapper.TypeHandler<DateTimeOffset>
{
public override void SetValue(IDbDataParameter parameter, DateTimeOffset value)
{
switch (parameter.DbType)
{
case DbType.DateTime:
case DbType.DateTime2:
case DbType.AnsiString: // Seems to be some MySQL type mapping here
parameter.Value = value.UtcDateTime;
break;
case DbType.DateTimeOffset:
parameter.Value = value;
break;
default:
throw new InvalidOperationException("DateTimeOffset must be assigned to a DbType.DateTime SQL field.");
}
}
public override DateTimeOffset Parse(object value)
{
switch (value)
{
case DateTime time:
return new DateTimeOffset(DateTime.SpecifyKind(time, DateTimeKind.Utc), TimeSpan.Zero);
case DateTimeOffset dto:
return dto;
default:
throw new InvalidOperationException("Must be DateTime or DateTimeOffset object to be mapped.");
}
}
}
private static int DateTimeOffsetMapperInstalled = 0;
public static void InstallDateTimeOffsetMapper()
{
// Assumes SqlMapper.ResetTypeHandlers() is never called.
if (Interlocked.CompareExchange(ref DateTimeOffsetMapperInstalled, 1, 0) == 0)
{
// First remove the default type map between typeof(DateTimeOffset) => DbType.DateTimeOffset (not valid for MySQL)
SqlMapper.RemoveTypeMap(typeof(DateTimeOffset));
SqlMapper.RemoveTypeMap(typeof(DateTimeOffset?));
// This handles nullable value types automatically e.g. DateTimeOffset?
SqlMapper.AddTypeHandler(typeof(DateTimeOffset), new DateTimeOffsetTypeHandler());
}
}
}
If you are using Dapper from source (not nuget), you could tweak the code to always force DateTimeKind of UTC. A more configurable option might be to create a new attribute for DateTime property values that allow you to specify date time kind as a hint to dapper. Dapper could look for DateTime properties with this attribute and when found could use it to specify the DateTime kind during ORM mapping. This might be a nice feature for core dapper as you are not the only one with this issue :)
ReferenceURL : https://stackoverflow.com/questions/12510299/get-datetime-as-utc-with-dapper
'IT story' 카테고리의 다른 글
jQuery Mobile이 동적으로 삽입 된 콘텐츠의 스타일 / 테마를 재평가하도록 강제 (0) | 2021.01.07 |
---|---|
밀리 초 단위의 C ++ 크로노 시스템 시간, 시간 작업 (0) | 2021.01.07 |
CSV 파일을 사용하여 플로팅 (0) | 2021.01.07 |
루프의 Python Lambda (0) | 2021.01.07 |
DOM 리플 로우 란 무엇입니까? (0) | 2021.01.07 |