如何通过LinqToDB向PostgreSQL的timestamp without time zone字段写入DateTime?
解决LinqToDB向PostgreSQL的timestamp without time zone字段写入DateTime的问题
问题场景
环境:C# + Linq2db + Postgres
表实体定义:
[Table("my_table", Schema = "myScheme")] public class TableEntity { // 其他字段... [Column("dt", DbType = "timestamp without time zone", DataType = DataType.DateTime)] public DateTime DT { get; set; } // 其他字段... }
设置实体值时指定了Local时区:
tableEntity.DT = DateTime.SpecifyKind(someDate, DateTimeKind.Local);
执行插入命令时:
await dataConn.InsertWithInt32IdentityAsync(tableEntity);
LinqToDB会自动将DateTimeKind.Local的时间转为UTC,导致PostgreSQL抛出异常:
Cannot write DateTime with Kind=UTC to PostgreSQL type 'timestamp without time zone', consider using 'timestamp with time zone'. Note that it's not possible to mix DateTimes with different Kinds in an array/range. See the Npgsql.EnableLegacyTimestampBehavior AppContext switch to enable legacy behavior.
要求必须使用timestamp without time zone字段,需解决写入问题。
解决方案
1. 直接将DateTime转为Unspecified时区
PostgreSQL的timestamp without time zone不存储时区信息,因此只需将DateTime的Kind设为Unspecified,LinqToDB就不会触发自动时区转换:
// 方法1:直接指定Kind为Unspecified tableEntity.DT = DateTime.SpecifyKind(someDate, DateTimeKind.Unspecified); // 方法2:基于原时间的Ticks创建新的Unspecified时间(适合Local转Unspecified) tableEntity.DT = new DateTime(someDate.Ticks, DateTimeKind.Unspecified);
2. 配置LinqToDB禁用自动时区转换
通过LinqToDB的PostgreSQL配置选项,全局禁用timestamp without time zone字段的Local到UTC自动转换:
var dataConn = new DataConnection(PostgreSQLTools.GetDataProvider(), connectionString); dataConn.AddMappingSchemaConfiguration(config => { config.SetPostgreSQLOptions(options => { // 关闭timestamp without time zone字段的自动时区转换 options.TimestampWithoutTimeZoneConversion = TimestampWithoutTimeZoneConversionMode.None; }); });
注:该配置需对应LinqToDB 3.0+版本,不同版本配置方式可能略有差异。
3. 为字段添加自定义类型转换器
在实体字段上绑定自定义转换器,强制将传入的DateTime转为Unspecified后再写入数据库:
// 自定义转换器 public class UnspecifiedDateTimeConverter : ValueConverter<DateTime, DateTime> { public UnspecifiedDateTimeConverter() : base( // 写入数据库前转为Unspecified input => DateTime.SpecifyKind(input, DateTimeKind.Unspecified), // 读取时保持原样 output => output) { } } // 在实体字段上指定转换器 [Column("dt", DbType = "timestamp without time zone", DataType = DataType.DateTime, ConverterType = typeof(UnspecifiedDateTimeConverter))] public DateTime DT { get; set; }
内容的提问来源于stack exchange,提问作者VladimirK
相关产品推荐
相关产品推荐

