在 NHibernate 中使用 OffsetDateTime
Using OffsetDateTime with NHibernate
我正在尝试将 NodaTime 的 OffsetDateTime
类型映射到 SQL 服务器,但我不确定如何解决 NodaTime 的 OffsetDateTime
和 SQL 服务器之间的阻抗DateTimeOffset
种类型。
我遇到的主要问题是让 LINQ 支持正常工作,因为 OffsetDateTime
没有比较运算符,例如 <
。这些系统在如何处理平等方面也有所不同。 NodaTime 同时考虑即时和偏移量,而 SQL 服务器只考虑即时。
2015-12-24 11:18+01:00
和2015-12-24 10:18+00:00
在SQL服务器中被认为是相等的,但在NodaTime中不相等。
我考虑过使用 ICompositeUserType
将 UTC date/time 和偏移量存储在单独的列中(类似于之前的 SQL Server 2008)但是 OffsetDateTime
没有一个 UTC/Instant 属性。因此,我看不到如何让 LINQ 查询中的 date.ToInstant()
正确映射到 ICompositeUserType
.
中的 属性
OffsetDateTime
应映射到 SQL 服务器 datetimeoffset
。 NHibernate 通过 IUserType
as described in this article 对自定义类型映射的支持对于完成这项工作至关重要。
虽然OffsetDateTime
没有直接实现IComparable
,但是可以用OffsetDateTime.Comparer.Instant
来比较。这在 LINQ 查询中可能仍然难以使用,但这是探索的一种途径。
有人可能应该编写一个 NHibernate-NodaTime 集成包来使这更简单。考虑到我之前为 RavenDB and for Dapper 做过这个,我会考虑它。 :)
抱歉,我没有更好的实际 "do this" 答案给你。
更新
我开始研究这个,并成功地为 OffsetDateTime
构建了一个 IUserType
,但它不适用于比较运算符 - 由于您描述的原因。我相信解决方案涉及扩展 linq 提供程序,类似于 in this blog post 中描述的技术。我还没有完整的工作示例,但我会在此处更新。
最终,您将无法编写:
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。 :)
我正在尝试将 NodaTime 的 OffsetDateTime
类型映射到 SQL 服务器,但我不确定如何解决 NodaTime 的 OffsetDateTime
和 SQL 服务器之间的阻抗DateTimeOffset
种类型。
我遇到的主要问题是让 LINQ 支持正常工作,因为 OffsetDateTime
没有比较运算符,例如 <
。这些系统在如何处理平等方面也有所不同。 NodaTime 同时考虑即时和偏移量,而 SQL 服务器只考虑即时。
2015-12-24 11:18+01:00
和2015-12-24 10:18+00:00
在SQL服务器中被认为是相等的,但在NodaTime中不相等。
我考虑过使用 ICompositeUserType
将 UTC date/time 和偏移量存储在单独的列中(类似于之前的 SQL Server 2008)但是 OffsetDateTime
没有一个 UTC/Instant 属性。因此,我看不到如何让 LINQ 查询中的 date.ToInstant()
正确映射到 ICompositeUserType
.
OffsetDateTime
应映射到 SQL 服务器 datetimeoffset
。 NHibernate 通过 IUserType
as described in this article 对自定义类型映射的支持对于完成这项工作至关重要。
虽然OffsetDateTime
没有直接实现IComparable
,但是可以用OffsetDateTime.Comparer.Instant
来比较。这在 LINQ 查询中可能仍然难以使用,但这是探索的一种途径。
有人可能应该编写一个 NHibernate-NodaTime 集成包来使这更简单。考虑到我之前为 RavenDB and for Dapper 做过这个,我会考虑它。 :)
抱歉,我没有更好的实际 "do this" 答案给你。
更新
我开始研究这个,并成功地为 OffsetDateTime
构建了一个 IUserType
,但它不适用于比较运算符 - 由于您描述的原因。我相信解决方案涉及扩展 linq 提供程序,类似于 in this blog post 中描述的技术。我还没有完整的工作示例,但我会在此处更新。
最终,您将无法编写:
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。 :)