我正在尝试将 NodaTime 的 OffsetDateTime
类型映射到 SQL Server,但我不确定如何解决 NodaTime 的 OffsetDateTime
和 SQL Server 的 DateTimeOffset
类型之间的阻抗。
我遇到的主要问题是让 LINQ 支持正常工作,因为 OffsetDateTime
没有比较运算符,例如 <
。这些系统在处理平等的方式上也有所不同。 NodaTime 同时考虑时间和偏移量,而 SQL Server 只考虑时间。2015-12-24 11:18+01:00
和 2015-12-24 10:18+00:00
在 SQL Server 中被视为相等,但在 NodaTime 中不相等。
我考虑使用 ICompositeUserType
将 UTC 日期/时间和偏移量存储在单独的列中(类似于 SQL Server 2008 之前),但 OffsetDateTime
没有 UTC/Instant 属性。因此,我看不到如何在 LINQ 查询中获取 date.ToInstant()
以正确映射到 ICompositeUserType
中的属性。
最佳答案
OffsetDateTime
应该映射到 SQL Server datetimeoffset
。 NHibernate 通过 IUserType
as described in this article 对自定义类型映射的支持对于完成这项工作至关重要。
虽然 OffsetDateTime
不直接实现 IComparable
,但您可以使用 OffsetDateTime.Comparer.Instant
来比较它们。这在 LINQ 查询中可能仍然难以使用,但它是一种探索途径。
有人可能应该编写一个 NHibernate-NodaTime 集成包来简化这个过程。考虑到我之前已经为 RavenDB 和 Dapper 做过这件事,我会考虑它。 :)
对不起,我没有更好的实际“做这个”的答案给你。
更新
我开始研究这个,并成功地为 IUserType
构建了一个 OffsetDateTime
,但它不适用于比较运算符 - 因为你描述的原因。我相信该解决方案涉及扩展类似于 in this blog post 描述的技术的 linq 提供程序。我还没有一个完整的工作示例,但我会在这里更新。
最终,您将无法编写:
session.Query<Foo>().Where(x => x.SomeODT > value)
因为
OffsetDateTime
没有比较运算符,所以它不会编译。相反,应该扩展 LINQ 提供程序以支持以下内容:
session.Query<Foo>().Where(x => OffsetDateTime.Comparer.Instant.Compare(x.SomeODT, value) > 0)
或者也许更干净:
session.Query<Foo>().Where(x => x.SomeODT.ToInstant() > value.ToInstant())
或者两者兼而有之。两者都会编译,但会在 LINQ 提供程序中没有适当支持的情况下抛出异常。
第二次更新
有人打败了我。现在有一组 NHibernate 扩展来支持 Noda Time 数据类型 in this project 。 :)
关于nhibernate - 在 NHibernate 中使用 OffsetDateTime,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34452792/