sql-server-2008 – 流畅的NHibernate SQL Server 2008 DATE列值问题

前端之家收集整理的这篇文章主要介绍了sql-server-2008 – 流畅的NHibernate SQL Server 2008 DATE列值问题前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
问候,

使用Fluent NHibernate在C#中使用sql Server 2008 DATE列时遇到问题.

当我尝试更新在1/1/1753(DATETIME的最小日期)之前的不可为空的DATE列中的值的记录时,我收到一条错误,指出它不能将NULL插入那列.如果值大于1/1/1753,则没有问题,保留正确的日期值.

这是我的模型文件

public class Table1 : model.DBObject
{
  public virtual Int32 TestID { get; private set; }
  public virtual String Description { get; set; }
  public virtual DateTime TestDate { get; set; }

  public Table1()
  {
  }

  public static Table1 Load(DBSess sess,Int32 TestID)
  {
      return (Table1)sess.Session.Get(typeof(Table1),TestID);
  }
}

我的映射文件

public class Table1Map : ClassMap<Table1>
{
  public Table1Map()
  {
    Table("[Table1]");
    Id(x => x.TestID).GeneratedBy.Identity();
    Map(x => x.Description).Not.Nullable();
    Map(x => x.TestDate).Not.Nullable().CustomType("date");
  }
}

正在执行的代码

using (DBSess sess = DBSess.Create())
{
  Table1 tbl = dal.Table1.Load(sess,1);
  tbl.Description = String.Format("Updated {0}",DateTime.Now);
  tbl.Save(sess);
  sess.Commit();
}

导出的NHibernate映射:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
  <class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="dal.Table1,dal,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" table="[Table1]">
    <id name="TestID" type="System.Int32,mscorlib,Version=4.0.0.0,PublicKeyToken=b77a5c561934e089">
      <column name="TestID" />
      <generator class="identity" />
    </id>
    <property name="Description" type="System.String,PublicKeyToken=b77a5c561934e089">
      <column name="Description" not-null="true" />
    </property>
    <property name="TestDate" type="date">
      <column name="TestDate" not-null="true" />
    </property>
  </class>
</hibernate-mapping>

log4net捕获的NHibernate.sql日志条目:

DEBUG2011-03-24 05:00:18 – SELECT table1x0_.TestID as TestID0_0_,table1x0_.Description as Descript2_0_0_,table1x0_.TestDate as TestDate0_0_ FROM [Table1] table1x0_ WHERE table1x0_.TestID=@p0;@p0 = 1
DEBUG2011-03-24 05:00:18 – UPDATE [Table1] SET Description = @p0,TestDate = @p1 WHERE TestID = @p2;@p0 = 'Updated 3/24/2011 5:00:18 PM',@p1 = NULL,@p2 = 1

log4net捕获的NHibernate日志条目的相关部分:

DEBUG2011-03-24 05:00:18 – Building an IDbCommand object for the sqlString: UPDATE [Table1] SET Description = ?,TestDate = ? WHERE TestID = ?
DEBUG2011-03-24 05:00:18 – Dehydrating entity: [dal.Table1#1]
DEBUG2011-03-24 05:00:18 – binding 'Updated 3/24/2011 5:00:18 PM' to parameter: 0
DEBUG2011-03-24 05:00:18 – binding '6/12/1700' to parameter: 1
DEBUG2011-03-24 05:00:18 – binding '1' to parameter: 2
DEBUG2011-03-24 05:00:18 – Obtaining IDbConnection from Driver
ERROR2011-03-24 05:00:19 – Could not execute command: UPDATE [Table1] SET Description = @p0,TestDate = @p1 WHERE TestID = @p2
System.Data.sqlClient.sqlException (0x80131904): Cannot insert the value NULL into column 'TestDate',table 'test2.dbo.Table1'; column does not allow nulls. UPDATE fails.
The statement has been terminated.
   at System.Data.sqlClient.sqlConnection.OnError(sqlException exception,Boolean breakConnection)
   at System.Data.sqlClient.sqlInternalConnection.OnError(sqlException exception,Boolean breakConnection)
   at System.Data.sqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.sqlClient.TdsParser.Run(RunBehavior runBehavior,sqlCommand cmdHandler,sqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj)
   at System.Data.sqlClient.sqlCommand.FinishExecuteReader(sqlDataReader ds,RunBehavior runBehavior,String resetOptionsString)
   at System.Data.sqlClient.sqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,Boolean returnStream,Boolean async)
   at System.Data.sqlClient.sqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,String method,DbAsyncResult result)
   at System.Data.sqlClient.sqlCommand.InternalExecuteNonQuery(DbAsyncResult result,String methodName,Boolean sendToPipe)
   at System.Data.sqlClient.sqlCommand.ExecuteNonQuery()
   at NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)

日志似乎显示了值“6/12/1700”与DATE列的参数的正确绑定,但sql语句引发了一个异常,表示它试图插入一个NULL.如果记录中的值大于“1/1/1753”,则不会有异常,并且该值正确保存.

我可以发布完整的NHibernate日志文件,如果有更多的信息可能有帮助.我不知道从哪里来看这个答案.

有没有人有任何想法在哪里寻找解决方案?

提前致谢,

〜吉姆·芬内尔

解决方法

对不起,只是意识到我应该发布这个问题的答案,而不是只是评论…请不要笑“新人!

通过进一步的讨论和测试,似乎这个问题与ADO.NET和NHibernate对数据类型DATE的MS sql 2008列的DbType.Date的使用有关.如果代码使用sqlDbType.Date而不是DbType.Date,则不会发生任何这样的问题,并且一切都将按照指定执行.

虽然使用DbType.Date可能对其他数据库类型看起来更“便携”,但由于ADO.NET DbType.Date的最低限制为1/1/1753,因此它会引入此问题.

这个问题的解决方法是告诉NHibernate列的类型是DATETIME2,它也支持早于1/1/1753的日期值.如果NHibernate映射是:

<property name="TestDate" type="datetime2">
  <column name="TestDate" sql-type="date" />
</property>

代码按预期执行,没有例外.

这太糟糕NHibernate不能识别它正在使用Mssql2008方言,并使用sqlDbTypes而不是DbTypes,但这种变通方法现在可以工作.

有关ADO.NET方面的更多信息,请参阅ADO.NET Insert Min Value into SQL Server 2008 Date column crashes.感谢@Graham Bunce的帮助.

我希望这些信息有助于将来遇到这个问题的任何人.

猜你在找的MsSQL相关文章