首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用Dapper获取DateTime作为UTC

用Dapper获取DateTime作为UTC
EN

Stack Overflow用户
提问于 2012-09-20 10:03:24
回答 3查看 28.4K关注 0票数 66

我使用Dapper将我的实体映射到Server。如果我用Kind=Utc保存一个Kind=Utc,当我把它读回来时,我会得到一个带有Kind=UnspecifiedDateTime,这会导致各种各样的问题。

示例:

代码语言:javascript
运行
复制
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);

此代码提供以下输出:

代码语言:javascript
运行
复制
20/09/2012 10:04:16 (Utc)
20/09/2012 10:04:16 (Unspecified)

我知道我应该使用DateTimeOffset,但不幸的是,SQL不支持这种类型。

有解决办法吗?我能告诉Dapper假设所有的日期都有DateTimeKind.Utc吗?更广泛地说,我有哪些选项可以自定义映射?

编辑:我目前的解决办法是在Dapper将结果具体化后修补日期,但它有点气味……

代码语言:javascript
运行
复制
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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-09-27 16:52:06

添加这个答案给其他人谁来寻找一个简单的修复。现在,通过在Dapper中添加SqlMapper.TypeHandler,这是可能的。

添加此类以将值从db转换为指定为UTC的日期时间。

代码语言:javascript
运行
复制
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的Global.asax文件中,将类型处理程序添加到dapper中。

代码语言:javascript
运行
复制
SqlMapper.AddTypeHandler(new DateTimeHandler());

如果需要确保始终以UTC的形式插入日期,则可以在SetValue方法上使用:

代码语言:javascript
运行
复制
parameter.Value = DateTime.SpecifyKind(value, DateTimeKind.Utc);
票数 111
EN

Stack Overflow用户

发布于 2018-04-11 16:53:22

我只想把我的完整解决方案放在这里,以便将DateTimeOffset / DateTimeOffset?字段/属性与MySQL 5.7数据库(不支持DbType.DateTimeOffset)无缝集成--基于上面@matt的答案:

代码语言:javascript
运行
复制
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());
        }
    }
}
票数 5
EN

Stack Overflow用户

发布于 2014-01-24 21:42:03

如果您是从源(而不是nuget)使用Dapper,则可以调整代码以始终强制UTC的DateTimeKind。一个更可配置的选项可能是为DateTime属性值创建一个新属性,该属性允许您指定日期时间类型作为对dapper的提示。Dapper可以使用这个属性查找DateTime属性,当发现它时,可以在ORM映射期间使用它来指定DateTime类型。对于核心dapper来说,这可能是一个很好的特性,因为您不是唯一有此问题的人:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12510299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档