Fluent NHibernate mapping for DateTime with default value

Viewed 4869

I know that there are many threads about this and I have read most of them. However for me a couple of things remain unclear and still do not work.

If I have on my database schema a field of type DateTime and I like to assign it a default value I would do something like this:

create table [mySchema].[MyTable](
    ObjectGuid uniqueidentifier CONSTRAINT Id PRIMARY KEY,
    SomeTextToStore nvarchar(128) NULL,
    CDate datetime NOT NULL DEFAULT GETDATE(),
    CUser nvarchar(64) DEFAULT CURRENT_USER
);
GO

(Don't know if it is important: I am using SQL Server Express 2014. Fluent configuration is for SQL Server 2012.)

This works fine when doing an INSERT from ISQL, inserts a timestamp of the moment when the record was added.

Using fluent I would write something like this:

Domain:

public class MyObject
{
    public virtual Guid Id {get; set}
    public virtual string SomeTextToStore {get; set;}
    public virtual DateTime? CDate {get; set;}
    public virtual string CUser {get; set;}
}

NOTE: I made CDate nullable!

And a mapping class like this:

class MyObjectMap : ClassMap<MyObject>
{
    public MyObjectMap()
    {
        Table("MySchema.MyTable");
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.SomeTextToStore).Length(128).Nullable();
        Map(x => x.CDate).Not.Nullable().Default("getdate()");
        Map(x => x.CUser).Not.Nullable().Default("CURRENT_USER);
    }
}

In the program (in my case this is a library that can be called from several type of programs) I do something like:

public void EnterSomeText()
{
    using (var session = sessionManager.OpenSession())
    {
        using (var transaction = session.BeginTransaction())
        {
            var myObj = new MyObject();
            myObj.SomeTextToStore("bla bla bla");
            session.SaveOrUpdate(myObj);
            transaction.Commit();
        }
        session.Close();
    }
}

This ends always in a DateTime overflow exception! (SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM)

It looks like not passing a value to the file CDate is causing the problem. When I add the default in my library like such it works:

...
myObj.SomeTextToStore("bla bla bla");
myObj.CDate = DateTime.Now;   // <---- Set the date here
session.SaveOrUpdate(myObj);
...

But this is not really the solution....

Questions:

  1. What am I doing wrong / missing ?
  2. What is the correct strategy when defining defaults? Doing it on the database or just in code? (When starting a plain new vanilla project, I would prefer doing everything from C# code, even create and later update the schema...)
  3. Regarding domain classes: Is it wise to create constructors, that fill fields with defaults?

I do this for the field CUser because in CUser I like to add the current user context

public MyObject()
{
   var o = System.Security.Principal.WindowsIdentity.GetCurrent();
   if (o != null)
   {
       CUser = o.Name;
   }  
}

Instead of filling the CDate field with the current date in my DB-access layer library I could do it also in the constructor of the domain-class like such:

public MyObject()
{
   var o = System.Security.Principal.WindowsIdentity.GetCurrent();
   if (o != null)
   {
       CUser = o.Name;
   } 
   CDate = DateTime.Now; 
}

Many thanks for your help and comments!

2 Answers
Related