【问题标题】:NHibernate won't persist DateTime SqlDateTime overflowNHibernate 不会持久化 DateTime SqlDateTime 溢出
【发布时间】:2009-03-14 04:49:28
【问题描述】:

我正在开发一个以 NHibernate 作为后端的 ASP.NET MVC 项目,但在获取一些日期以写回我的 SQL Server 数据库表时遇到了一些麻烦。

这些日期字段不可为空,因此这里关于如何设置可空日期时间的许多答案都没有帮助。

基本上,当我尝试保存具有 DateAdded 和 LastUpdated 字段的实体时,我得到了 SqlDateTime 溢出异常。过去我遇到过类似的问题,我试图将日期时间字段写入 smalldatetime 列,更新列上的类型似乎可以解决问题。我的直觉是,它的表定义或某些类型的不兼容数据类型会出现问题,并且溢出异常有点笨拙。

我附上了一个表定义示例和 NHibernate 尝试运行的查询,任何帮助或建议将不胜感激。

CREATE TABLE [dbo].[CustomPages](
    [ID] [uniqueidentifier] NOT NULL,
    [StoreID] [uniqueidentifier] NOT NULL,
    [DateAdded] [datetime] NOT NULL,
    [AddedByID] [uniqueidentifier] NOT NULL,
    [LastUpdated] [datetime] NOT NULL,
    [LastUpdatedByID] [uniqueidentifier] NOT NULL,
    [Title] [nvarchar](150) NOT NULL,
    [Term] [nvarchar](150) NOT NULL,
    [Content] [ntext] NULL
)

exec sp_executesql N'INSERT INTO CustomPages (Title, Term, Content, LastUpdated, DateAdded, StoreID, LastUpdatedById, AddedById, ID) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)',N'@p0 
nvarchar(21),@p1 nvarchar(21),@p2 nvarchar(33),@p3 datetime,@p4 datetime,@p5 uniqueidentifier,@p6 uniqueidentifier,@p7 uniqueidentifier,@p8 uniqueidentifier',@p0=N'Size and Colour 
Chart',@p1=N'size-and-colour-chart',@p2=N'This is the size and colour chart',@p3=''2009-03-14 14:29:37:000'',@p4=''2009-03-14 
14:29:37:000'',@p5='48315F9F-0E00-4654-A2C0-62FB466E529D',@p6='1480221A-605A-4D72-B0E5-E1FE72C5D43C',@p7='1480221A-605A-4D72-B0E5-E1FE72C5D43C',@p8='1E421F9E-9A00-49CF-9180-DCD22FCE7F55'

为了响应答案/cmets,我使用 Fluent NHibernate,生成的映射如下

  public CustomPageMap() {

            WithTable("CustomPages");

            Id( x => x.ID, "ID" )
                .WithUnsavedValue(Guid.Empty)
            .   GeneratedBy.Guid();

            References(x => x.Store, "StoreID");

            Map(x => x.DateAdded, "DateAdded");
            References(x => x.AddedBy, "AddedById");
            Map(x => x.LastUpdated, "LastUpdated");
            References(x => x.LastUpdatedBy, "LastUpdatedById");


            Map(x => x.Title, "Title");
            Map(x => x.Term, "Term");
            Map(x => x.Content, "Content");

        }  

    <?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false" assembly="MyNamespace.Core" namespace="MyNamespace.Core">
<class name="CustomPage" table="CustomPages" xmlns="urn:nhibernate-mapping-2.2">
<id name="ID" column="ID" type="Guid" unsaved-value="00000000-0000-0000-0000-000000000000"><generator class="guid" /></id>
<property name="Title" column="Title" length="100" type="String"><column name="Title" /></property>
<property name="Term" column="Term" length="100" type="String"><column name="Term" /></property>
<property name="Content" column="Content" length="100" type="String"><column name="Content" /></property>
<property name="LastUpdated" column="LastUpdated" type="DateTime"><column name="LastUpdated" /></property>
<property name="DateAdded" column="DateAdded" type="DateTime"><column name="DateAdded" /></property>
<many-to-one name="Store" column="StoreID" /><many-to-one name="LastUpdatedBy" column="LastUpdatedById" />
<many-to-one name="AddedBy" column="AddedById" /></class></hibernate-mapping>

【问题讨论】:

  • 您的表和 SQL 似乎没问题。如果您尝试手动运行该 SQL 查询,它是否有效?可能值得在这里发布代码和休眠映射文件
  • 是的,查询在 SQL 查询分析器中运行正常,除了我必须将日期时间周围的双单引号(作为 utc 样式字符串)更改为单引号,此查询由 nhibernate 生成

标签: sql-server nhibernate datetime


【解决方案1】:

其实背后的原因是:

当 NHibernate 从 db 中读取行时,值为 null,这就是 session 记住的。当对象被 NHibernate 重新水化时,日期设置为值 DateTime.MinValue。当 Session 与 db 同步时,NHibernate 假定发生了某些变化,因为 currentState 和 previousState 不同并尝试更新行。这反过来又失败了,因为 DateTime.MinValue 不适合 SqlServer 日期时间列。

解决办法: 通过放置使您的日期时间可以为空?在日期时间结束时,例如 DateTime?Nullable

完整的文章可以在以下位置找到:nhibernate-sqldatetime-overflow-issue

【讨论】:

    【解决方案2】:

    我遇到了相同的问题表,其中包含不可为空的日期时间列和保存时的 SqlDateTime 溢出。

    在我的情况下,实际问题是保存触发了 session.flush,这会导致更新之前使用同一会话加载的某些对象。该对象确实存在“应使用可空日期时间字段的日期时间字段”问题。

    换句话说:尝试在保存或更新之前执行 session.flush 以检查问题是否可能是由于之前使用相同的会话对象引起的。

    希望对任何人都有帮助。

    【讨论】:

      【解决方案3】:

      为什么@p3 和@p4 有2x 单引号?复制粘贴出错?

      我无法检查(这里没有安装SQL),但是millisecond separator应该不是“点”,即“2009-03-14 14:29:37.000”

      @p3 是“之前”,@p4 是“之后”:

      exec sp_executesql
        N'INSERT INTO CustomPages (Title, Term, Content, LastUpdated, DateAdded, StoreID, LastUpdatedById, AddedById, ID)
        VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)',
        N'@p0 nvarchar(21),@p1 nvarchar(21),@p2 nvarchar(33),@p3 datetime,@p4 datetime,@p5 uniqueidentifier,@p6 uniqueidentifier,@p7 uniqueidentifier,@p8 uniqueidentifier',
      
          @p0=N'Size and Colour Chart',
          @p1=N'size-and-colour-chart',
          @p2=N'This is the size and colour chart',
          @p3=''2009-03-14 14:29:37:000'', --quotes + dot wrong?
          @p4='2009-03-14 14:29:37.000', --quotes + dot correct?
          @p5='48315F9F-0E00-4654-A2C0-62FB466E529D',
          @p6='1480221A-605A-4D72-B0E5-E1FE72C5D43C',
          @p7='1480221A-605A-4D72-B0E5-E1FE72C5D43C',
          @p8='1E421F9E-9A00-49CF-9180-DCD22FCE7F55'
      

      【讨论】:

      • 是的,我认为它呈现日期的方式也有点奇怪,但是它在查询分析器中确实有效,除了我必须将双引号换成单引号。我查看了 nhibernate doco 的第 5 章,以为我可以告诉 nhibernate 如何纠正方言,但看起来不太可能
      • SQL Server 的 2009-03-14 14:29:37:000 格式是错误的
      • 方言可能是你的问题。为什么你说它看起来不可能设置?你是如何创建你的 SessionFactory 的?您是从配置文件中读取它,还是以编程方式创建它?
      【解决方案4】:

      您问题中的 SQL 脚本在我的 SQL 2005 安装中执行得很好(一旦我修复了 gbn 发现的报价问题)。而且您的映射看起来也很好。很抱歉帮不上什么忙。

      【讨论】:

        【解决方案5】:

        我使用 s#architecture/fluentnhibernate 创建此映射,我已升级到最新版本,它似乎工作正常。

        【讨论】:

          【解决方案6】:

          仅供参考,我一直致力于将现有应用程序从各种嵌入式数据访问方法迁移到 NHibernate。这个问题很快就出现了,我找到了一个简单的解决方案,可以最大限度地减少对现有功能应用程序代码的影响。因为我们在某些情况下是逐层迁移的,所以数据类接口需要尽可能保持稳定。这里的解决方案是继续为公共接口使用 DateTime 类型,为私有字段类型添加扩展方法以将 MinValue 转换为 null 并返回到访问器中的私有字段,并将 nHibernate 映射到私有字段。

          JF

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-12
            • 2011-02-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多