5

Consider the following simple C# class:

public class Entity
{
    public Entity() { }
    public virtual int Id { get; private set; }
    public virtual DateTime DateCreated { get; private set; }
}

Mapped with the following simple NHibernate mapping:

<class name="Entity" mutable="false">
    <id name="Id">
        <generator class="native">
    </id>
    <property name="DateCreated"/>
</class>

To the following simple database schema:

CREATE TABLE Entity (
    Id int IDENTITY(1,1) PRIMARY KEY,
    DateCreated datetime NOT NULL DEFAULT getUtcDate()
)

When creating a new instance of the Entity and saving to the database, how do you instruct NHibernate to use the database's default value for the DateCreated column if its value is null? Alternatively, how can I specify that NHibernate should use the result of the getUtcDate() function as the value for the DateCreated field upon insertion?

While I could easily add

DateCreated = DateTime.Now;

into the Entity constructor, this is using the application server's local clock, and I need to use the database's local clock to ensure consistency when there are multiple application servers each with their potentially non-synchronized local clocks.

2
  • Can't answer the nhibernate question, but in general you'll want to store dates in your database as UTC. No matter what their source, UTC is the same across all servers (assuming the clocks are accurate). Commented Jul 14, 2009 at 16:45
  • In general, yes, agreed. That's why I specified getUtcDate() instead of getDate() in the question. :) Commented Jul 14, 2009 at 17:53

2 Answers 2

4

You can specify that the property is generated by the database:

NHibernate Mapping - property

So for your case you would want to specify:

generated="insert"

This way NHibernate knows after an INSERT it will have to refresh the entity, but after updates DateCreated will not be changed.

You might also have to specify:

update="false" insert="false"

I've never used generated, and I'm not sure if NHibernate infers to set those or you have to do it explicitly.

Sign up to request clarification or add additional context in comments.

4 Comments

Not sure how I missed that in the docs (nhforge.org/doc/nh/en/index.html#mapping-generated); I swear I looked at least two times and must have stared right at it.
I like your doc links better. I need to start making NH Forge a regular stop.
Unfortunately this doesn't entirely answer the question. While it works for inserts, for updates you'll need to employ database triggers. NHibernate still does not send "DEFAULT" or "GETUTCDATE()" as part of the UDPATE.
@JosephDaigle The default value in SQL Server is intended only for inserted rows. Once inserted, SQL Server has no idea whether an update with a null-valued column is intentional or not, and isn't going to guess.
1

I had a similar issue. I had to add the attribute dynamic-insert="true" to my class mapping.
From the documentation:

dynamic-insert (optional - defaults to false): specifies that INSERT SQL should be generated at runtime and contain only the columns whose values are not null.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.