up vote 1 down vote favorite
1

I am working on an ASP.NET MVC project with NHibernate as the backend and am having some trouble getting some dates to write back to my SQL Server database tables.

These date fields are NOT nullable, so the many answers here about how to setup nullable datetimes have not helped.

Basically when I try to save the entity which has a DateAdded and a LastUpdated fields, I am getting a SqlDateTime overflow exception. I have had a similar problem in the past where I was trying to write a datetime field into a smalldatetime column, updating the type on the column appeared to fix the problem. My gut feeling is that its going to be some problem with the table definition or some type of incompatible data types, and the overflow exception is a bit of a bum steer.

I have attached an example of the table definition and the query that NHibernate is trying to run, any help or suggestions would be greatly appreciated.

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'

In response the the answers/comments, I am using Fluent NHibernate and the generated mapping is below

  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>
flag
Your table and the SQL seem ok. Does that SQL query work if you try running it by hand? It might be worth posting the code and the hibernate mapping file here – Andy White Mar 14 '09 at 7:27
Yes the query does run okay in SQL Query Analyzer, except I have to change the double single quotes around the datetimes (as utc style strings) to single quotes, this query is generated by nhibernate – chris raethke Mar 14 '09 at 15:02

7 Answers

up vote 5 down vote

Actually the reason behind the scean is :

When NHibernate reads the row from the db, the value is null, and that's what the session remembers. When the object is rehydrated by NHibernate the Date is set to the value DateTime.MinValue. When the Session is synchronized with the db, NHibernate assumes that something has changed, because the currentState and the previousState are different and tries to update the row. Wich in turn fails, because DateTime.MinValue won't fit into a SqlServer datetime column.

The solution: make your datetime nullable either by putting ? at end of Datetime like DateTime? or Nullable

complet article can be found at: nhibernate-sqldatetime-overflow-issue

Zafar Ullah

www.hyperlinksolutions.net

link|flag
Solved my problem. – AndrĂ© Pena Jan 17 at 6:10
up vote 0 down vote

Why do @p3 and @p4 have 2x single quotes? Copy and paste error?

I can't check (don't have SQL installed here), but should the millisecond separator not be "dot", that is, "2009-03-14 14:29:37.000"

@p3 is "before", @p4 is "after" here:

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'
link|flag
Yes, I thought the way it rendered the dates was a bit weird also, however it does work in query analyzer except I have to swap the double quotes for single quotes. I looked into chapter 5 of the nhibernate doco thinking I could tell nhibernate how to correct the dialect, but it doest look possible – chris raethke Mar 14 '09 at 15:04
The 2009-03-14 14:29:37:000 format is wrong though for SQL Server – gbn Mar 15 '09 at 16:56
The dialect might be your problem. Why do you say it doesn't look possible to set that? How are you creating your SessionFactory? Are you reading it from a config file, or creating it programmatically? – Andy White Mar 15 '09 at 20:21
up vote 0 down vote

The SQL script in your question executed just fine on my SQL 2005 installation (once I fixed the quote issues picked up by gbn). And your mapping also looks fine. Sorry to be of so little help.

link|flag
up vote 0 down vote

Did you find a solution for this issue, Chris?

link|flag
up vote 0 down vote

I was using s#architecture/fluentnhibernate to create this mapping, I have upgraded to the latest version and it seems to be working fine.

link|flag
up vote 0 down vote

Hi Chris,

I am using Sharp most update trunk ( 16/jun ) as well. When I don't input anything in the textbox of date, I got the same error as well. The date field in Core\xxx.cs is [NotNull] and in table, it is not allow nulll as well.

Could you give me some advise as well?

Thanks a lot.

link|flag
You should be checking the ModelState or the equivalent list from NHibernate validation to decide whether you can submit the save or not first, not setting the value of the not nullable date will mean its value is DateTime.MinValue which is out of range for a SQL DateTime – chris raethke Jul 10 '09 at 1:12
up vote 0 down vote

Just an FYI, I have been working on migrating an existing application to NHibernate from a variety of embedded Data Access approaches. This issue came up quickly, and I found an easy solution that minimized impact to the existing functional application code. Because we are migrating by layer in some cases, the data class interface needed to remain stable if at all possible. The solution here was to continue to use DateTime types for the public interface, add extension methods to the private field types to convert from MinValue to null and back on the private fields in the accessors, and map nHibernate to the private fields.

JF

link|flag

Your Answer

get an OpenID
or
never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.