在自己的挫败感中苦苦寻找解决方案后,我终于找到了一个解决方案,可以使我的api消费者不必将DateTime字符串强制转换为一个丑陋、冗长、令人不安的表达式。
我还希望我的模型透明地使用DateTimeOffset而不是DateTime,这将允许我在未来重构数据库并最终使用DateTimeOffset,即使到目前为止我不需要处理时区。
我的限制是我不能更新我的遗留数据库,所以这里是解决方案。
这个解决方案适合您吗?
只有在以下情况下,此解决方案才有用:
- 您不能(或不想)更新您的db列类型(如果您可以,您应该解决问题)
- 您使用或可以更改实体以使用DateTimeOffset而不是DateTime(如果这是一个新的api,请考虑这样做以符合odata标准,并允许您在未来重构底层数据库)
- 您不需要处理不同的时区(这可以做到,但您需要努力解决方案)
- 您使用EF Core >= 2.1
解决方案
更新您的实体使用
DateTimeOffset。
public class MyEntity {
[...]
public DateTimeOffset CreatedDateTime { get; set; }
public DateTimeOffset ModifiedDateTime { get; set; }
[...]
}
- 创建一个ValueConverter
public static class ValueConvertes
{
public static ValueConverter<DateTimeOffset, DateTime> DateTimeToDateTimeOffset =
new ValueConverter<DateTimeOffset, DateTime>(
model => model.DateTime,
store => DateTime.SpecifyKind(store, DateTimeKind.UTC));
}
更新您的模型映射。
public void Configure(EntityTypeBuilder<QuestionQML> builder)
{
builder.ToTable("MyEntityTable");
builder.Property(e => e.CreatedDateTime)
.HasColumnName("CreatedDateTime")
.HasConversion(ValueConvertes.DateTimeToDateTimeOffset);
builder.Property(e => e.ModifiedDateTime)
.HasColumnName("ModifiedDateTime")
.HasConversion(ValueConvertes.DateTimeToDateTimeOffset);
[...]
}
这使您能够以以下方式进行筛选:
?$filter=CreatedDateTime gt 2010-01-25T02:13:40Z
?$filter=CreatedDateTime gt 2010-01-25T02:13:40.01234Z
?$filter=CreatedDateTime gt 2010-01-25
特别感谢
chris-clark。
编辑:
当数据库中存储的日期时间为UTC时,可以使用正确的代码DateTimeKind.UTC。如果您在不同的时区存储,则需要将Kind设置为您使用的时区,但这会改变结果中显示日期时间的方式,例如,对于英国时区,显示为Z(GMT时间)或+01:00(BST时间)。
datetime2
?如果您使用datetime2
,您的查询应该可以正常工作。 - itminus