C# 处理MongoDB在与服务定位器模式一起使用时如何存储日期时间

C# 处理MongoDB在与服务定位器模式一起使用时如何存储日期时间,c#,mongodb,interface,mongodb-.net-driver,service-locator,C#,Mongodb,Interface,Mongodb .net Driver,Service Locator,我和我的同事在辩论中陷入僵局,我们非常感谢其他人的意见 我们利用服务定位器模式和一个公共接口来抽象所有的数据访问,这样我们就可以随着需求的变化轻松地在不同的数据源之间进行交换。我们的调用代码没有指示数据存储在何处或如何存储。它只是通过服务注册表提供的服务访问数据 当我们在对象上有DateTime字段并将其存储到MongoDB数据源时,就会出现我们正在讨论的问题 我注意到的是,当我们在C#中有一个对象,它带有日期时间,它显示为正确的时间。当我们使用MongoVUE登录MongoDB服务器来检查对象

我和我的同事在辩论中陷入僵局,我们非常感谢其他人的意见

我们利用服务定位器模式和一个公共接口来抽象所有的数据访问,这样我们就可以随着需求的变化轻松地在不同的数据源之间进行交换。我们的调用代码没有指示数据存储在何处或如何存储。它只是通过服务注册表提供的服务访问数据

当我们在对象上有DateTime字段并将其存储到MongoDB数据源时,就会出现我们正在讨论的问题

我注意到的是,当我们在C#中有一个对象,它带有日期时间,它显示为正确的时间。当我们使用MongoVUE登录MongoDB服务器来检查对象时,它会显示正确的时间。但是当我们检索对象时,日期时间现在是UTC。这显然会在将内存中的日期时间与从MongoDB数据源检索到的对象中的日期时间进行比较时产生问题

我知道Mongo在内部将日期时间存储为UTC时间。我甚至理解为什么当你调用它时它可能返回UTC

辩论从这里开始

有人认为这只是一个表面问题,只是显示日期时的问题。因此,我们只需在接口层中调用.ToLocalTime。我不同意,并断言这会危险地破坏我们在实现服务定位器模式时创建的抽象层。它还提出了关于与这些日期时间的交互的问题,因为它涉及触发其他事件

我在其他地方读到的是,我们应该将时间存储为字符串,特别是UTC格式的一些标准。以这种方式,接口层不知道或不关心DateTime是如何存储的,我们的对象也不知道,因为每个数据源都会以相同的方式存储该字符串

我使用ISO 1806格式成功地做到了这一点,但我的同事认为这是一个“黑客”修复,使用.toLocalTime是处理这种情况的适当方法

我对其他人对这个话题的看法很感兴趣


提前感谢您的输入。

您为什么不首先将UTC存储在数据库中?在大多数情况下,
DateTime
应该存储在UTC中,因为它通常指的是一个时间点。这适用于任何物理意义上的时间,以及任何假设时间是单调的、递增的和唯一的,这些都不适用于大多数当地时间

有时候,使用当地时间是有意义的:假设一辆公共汽车每天早上9点发车。这意味着两个连续事件之间的时间间隔为24小时。但是,如果时区有DST,则为23小时,分别为25小时,每年一次

然而,如果你需要处理这类数据,一个简单的
DateTime
就不行了;DST规则可以更改,时区可以更改,等等。在C#中,将应用的DST规则是当前有效的规则,即使日期是“历史”日期。因此,使用历史日期计算日期会造成严重破坏。如果您真的需要处理这个问题,至少应该存储时间所在的时区(不仅是偏移量,甚至只是一个
isLocal
标志)

在数据库中存储可以二进制存储的文本信息对我来说似乎不是很优雅,在中间层更改值也不是很优雅。前者效率低下,并且受到前面提到的当地时间特性的影响,后者只有第二个问题


顺便说一句,为了实现后者,您可以使用
[BsonDateTimeOptions(Kind=DateTimeKind.Local)]
装饰该属性,这将为您进行转换,但当然也会遇到同样的问题。

我们进一步讨论了。在当前时间,将所有日期时间重新计算为UTC时间存储是不现实的。我们决定做的是用前缀UTC标记字段,这对于明确特定时区至关重要。我们确保进入的datetime对象是UTC,并且mongo不会转换它,因为它已经是UTC了。然后我们知道UTC也将推出。我们已经同意,如果我们重构所有代码并删除UTC前缀,我们将稍后返回。前缀并不漂亮,但它可以解决当前的问题,并且不会破坏抽象。为什么不在UTC上运行服务器呢?不需要标记。业务逻辑与UTC时间的关系更加清晰一致,并且您可以在适用的情况下转换为本地时间。如果您的服务应该提供包括本地日期格式在内的信息,那么在服务层逻辑中转换它们。有时,您可能还希望在模型层内的本地时间进行操作(例如,如果需要解决夏令时问题)。它与任何其他数据转换一样。有一个参考点是必要的,它不必打破你的设计模式。