【发布时间】:2011-03-24 21:13:50
【问题描述】:
您好,
我在使用 Fluent NHibernate 的 C# 中使用 SQL Server 2008 DATE 列时遇到问题。
当我尝试更新在 1753 年 1 月 1 日(DATETIME 的最小日期)之前在不可为空的 DATE 列中具有值的记录时,我收到一条错误消息,指出它可以t 在该列中插入 NULL。如果该值大于 1753 年 1 月 1 日,则没有问题并保留正确的日期值。
这是我的模型文件:
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, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="TestID" />
<generator class="identity" />
</id>
<property name="Description" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, 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, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, 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 日志文件,如果那里有更多信息可能会有所帮助。我不确定从这里到哪里寻找答案。
有人对在哪里寻找解决方案有任何想法吗?
提前致谢,
~吉姆·芬内尔
【问题讨论】:
-
我仍然没有找到任何解释。我开始怀疑这是 NHibernate 中的一个错误。是否有其他人在使用小于最小 DATETIME 值的 SQL 2008 DATE 值时遇到类似问题?如果您成功更新了小于 1/1/1753 的 DATE 值(没有将它们更改为 NULL),您愿意分享我们的映射和模型文件的代码 sn-ps 用于相关列和表吗?
-
通过进一步的讨论和测试,已经确定这个问题与ADO.NET和NHibernate对MS SQL 2008数据类型DATE的列的DbType.Date的使用有关。如果代码使用 SqlDbType.Date 而不是 DbType.Date,则不会发生此类问题,并且一切都会按指定执行。虽然 DbType.Date 的使用对于其他数据库类型似乎更“可移植”,但它确实引入了这个问题,因为 ADO.NET DbType.Date 的最小值限制为 1/1/1753。
标签: sql-server-2008 exception date fluent-nhibernate