【问题标题】:Incercept when DateTime.Now is used when writing to a Database在写入数据库时​​使用 DateTime.Now 时拦截
【发布时间】:2011-09-08 00:27:21
【问题描述】:

well known 在数据库中,您应该将日期存储在通用时间坐标中。

我正在寻找一种方法来了解开发人员在写入数据库时​​何时滥用 DateTime.Now。

我们使用的是 Sql Server 2008,带有 EF4 或 nHibernate 3.0。

当日期时间的值包含在低层的时区信息时,是否可以截取它的值,比如在 Sql Server 中,或者在 NH/EF 中?

【问题讨论】:

  • 您的“众所周知”的事实本身就有点主观。虽然通用时间可能是一个很好的默认值,但有时本地时间更方便也更合适。
  • 不,以 UTC 存储时间并不总是正确的。例如,公共汽车或火车时刻表在 UTC 中没有意义,但应该以本地时间存储。这同样适用于约会。
  • 有关 UTC 与本地时间的深入讨论,另请参阅 stackoverflow.com/questions/2580478/…。请记住,datetime 不包含实际的时区信息,而仅包含 Local, UtcUnspecified 的标志。
  • @mnemosyn 当公共汽车或火车穿越时区时,什么是“当地时间”?
  • @RedFilter:我提到的线程讨论了一些问题。当然,由于 DST,当地时间并不总是可逆的:可能会出现歧义。尽管如此,设置为晚上 7 点的约会会在晚上 7 点重新生效,即使它转移了一周(例如,跨越 DST 边界),并且正确应用这些规则可能非常棘手 - 因此,在极少数情况下,当地时间让事情变得更容易。

标签: .net sql-server nhibernate entity-framework


【解决方案1】:

您不应该引入代码来对您的开发人员编码风格强制执行规则。您在应用程序中引入了不必要的开销。有一些方法可以解决这个问题:

a) 定期进行代码审查并确保所有签入的代码都经过验证

b) 另一种方法是在您的数据模型中强制执行此操作。你为什么不在这个字段上使用 DateTimeOffset 属性,不用担心。

【讨论】:

    【解决方案2】:

    您可以添加以下事件监听器:

    public class DateTimeEventListener : IPreUpdateEventListener,
                                         IPreInsertEventListener
    {
        public bool OnPreUpdate(PreUpdateEvent e)
        {
            foreach (var value in e.State)
                if (value is DateTime && ((DateTime)value).Kind != DateTimeKind.Utc)
                    throw new Exception("Non-UTC DateTime used");
        }
    
        public bool OnPreInsert(PreInsertEvent e)
        { /*Same as OnPreUpdate*/ }
    }
    

    (这是完全未经测试的,可能会因从数据库中检索到的值而失败。用作起始点)

    【讨论】:

      【解决方案3】:

      撇开日期是否应该以 UTC 格式存储的争论不谈,在代码中检查此类内容的地方是在构建过程中,或者在构建过程中失败,使用预提交挂钩。

      后者仅允许开发人员提交符合您的标准的代码。在数据库层这样做已经太晚了,IMO。

      【讨论】:

        【解决方案4】:

        处理不良数据的关键是尽早将其消除。当您到达数据库层时,再做任何有用的事情都为时已晚。

        在运行时在 SQL 查询中可能无法检测到 DateTime.Now 的使用。您最好检查您的代码并消除所有使用DateTime.Now。到处。设置一个编码标准,以便整个程序中的所有日期和时间都以 UTC 表示,除非它们必须在本地时间或其他时区输出。这将是解决问题的更好的长期解决方案。

        【讨论】:

        • 不可能?我们在这里不使用这个词。
        【解决方案5】:

        我认为在 NHibernate 中,您可以使用拦截器类来覆盖 OnSave 上的 OnLoad 等基本方法。在插入数据库之前,您可以尝试拦截属性类型并在那里管理您的日期。

        看这里:

        http://knol.google.com/k/fabio-maulo/nhibernate-chapter-11-interceptors-and/1nr4enxv3dpeq/14#

        【讨论】:

          【解决方案6】:

          您可以在您的数据库中编写一个触发器,当您希望现在出现的 DateTime 现在不在 UTC 附近时记录(或执行其他操作)。

          您现在可以将您的 EF 或 NHibernate 层默认日期字段设置为 UTC,因此开发人员无需设置它们。

          可能更好,您可以搜索 DateTime.Now 的代码并查看用法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-03-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-07-03
            相关资源
            最近更新 更多