The solution is to override the DateTime type and make NHibernate treat it as DateTimeOffset.
namespace AspNetCoreExample.Infrastructure.NHibernateNpgsqlInfra
{
using System.Data.Common;
using NHibernate.SqlTypes;
using Npgsql;
public class NpgsqlDriverExtended : NHibernate.Driver.NpgsqlDriver
{
// this gets called when an SQL is executed
protected override void InitializeParameter(DbParameter dbParam, string name, SqlType sqlType)
{
if (sqlType is NpgsqlExtendedSqlType && dbParam is NpgsqlParameter)
{
this.InitializeParameter(dbParam as NpgsqlParameter, name, sqlType as NpgsqlExtendedSqlType);
}
else
{
base.InitializeParameter(dbParam, name, sqlType);
if (sqlType.DbType == System.Data.DbType.DateTime)
{
dbParam.DbType = System.Data.DbType.DateTimeOffset;
}
}
}
// NpgsqlExtendedSqlType is used for Jsonb
protected virtual void InitializeParameter(NpgsqlParameter dbParam, string name, NpgsqlExtendedSqlType sqlType)
{
if (sqlType == null)
{
throw new NHibernate.QueryException(string.Format("No type assigned to parameter '{0}'", name));
}
dbParam.ParameterName = FormatNameForParameter(name);
dbParam.DbType = sqlType.DbType;
dbParam.NpgsqlDbType = sqlType.NpgDbType;
}
}
}
With the code above, the utc 2018-05-04T17:37:00.000Z is now correctly persisting as 2018-05-05 01:37:00+08.
Sample wiring of NpgsqlDriver: https://github.com/MichaelBuen/AspNetCoreExample/blob/b78b97f085730cfb9494c3ec15085cccf7f761be/AspNetCoreExample.Ddd.Mapper/_TheMapper.cs#L32
If you are using Npgsql version 4.0 with NHibernate, you don't need this fix anymore. With Npgsql version 4.0, you can just add TimeZone=UTC to NHibernate's connection string. An example: http://www.ienablemuch.com/2018/06/utc-all-things-with-nhibernate-datetime-postgres-timestamptz.html
No comments:
Post a Comment