4
votes

I am getting (a little bit to) deep into automapping with the fluent interface of NHibernate. Very nice thing, but I ran into a little problem with DateTimes. I need to change the data format to timestamp, otherwise NHibernate truncates milliseconds.

I found several sources of information, the best one was: AutoMapping Info 1 where he is changing the column name and type of a property. The problem is, there was a change in the fluent automappings, according to this document.

Now I cant figure out how to get the automapping to "change the type". I tried the following code, but I am stuck. Again, what I want to do is simply tell the automapper to:

Use Timestamps for DateTime to prevent the truncation of milliseconds when using automapping.

Anyone got an idea? Code so far:

   public class DateTimeToTimestamp : IClassConvention  
{  
    public bool Accept(IClassMap target)
    {
        return target.GetType() == typeof(DateTime);
    }

    public void Apply(IClassMap target)
    {
        throw new NotImplementedException();
    }
}

Ok, thanks a lot for the answer... Its enough comfort for me that way. If I really have 3 classes which need this precision, I can deal with writing it three times. Especially because the mapping of all other properties works still perfectly, and the following code only alternates the one property I want to... Very nice!

If anybody knows a more generic approach, feel free to add it, but for now, I am happy!

Code for my case was:

    public class DateTimeToTimestamp : IAutoMappingOverride<CustomTime>
{
    public void Override(AutoMap<CustomTime> mapping)
    {
        mapping.Map(x => x.ScanDate).CustomTypeIs("timestamp");
    }
}
3

3 Answers

2
votes

You can override a specific class. Not sure how to do this on a more general level though.

public class AlbumMappingOverride : IAutoMappingOverride<Album>
{
    public void Override(AutoMap<Album> mapping)
    {
        mapping.Map(x => x.Created).CustomSqlTypeIs("timestamp");
    }
}
11
votes

To expand on Derek's answer, in order to do it on a more general level, you would use an automapping convention:

public class TimestampTypeConvention : IPropertyConvention, IPropertyConventionAcceptance
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Type == typeof (DateTime));
    }

    public void Apply(IPropertyInstance instance)
    {
        instance.CustomType<TimestampType>();
    }
}
2
votes

Danie's answer is the one to use, though there is a small change that needs to be made to the Apply() method for it to work: CustomSqlType("timestamp") -> CustomType("Timestamp"). I verified this as i have just implemented the solution in my own project.

Note: I tried to submit an edit to Daniel's answer above, but couldn't because the change was too small so here is the corrected code:

public class TimestampTypeConvention : IPropertyConvention, IPropertyConventionAcceptance
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Type == typeof (DateTime));
    }

    public void Apply(IPropertyInstance instance)
    {
        instance.CustomType("Timestamp");
    }
}

In addition, seeing as i am writing a new post, here is a stripped-down example of how you create a session factory with Fluent NHibernate that uses the convention, for the benefit of others who may not know:

var factory = Fluently.Configure()
        .Mappings(m => m.FluentMappings.Conventions.Add(new TimestampConvention()))
        .BuildSessionFactory();

Kudos to this post for making me aware of this, as i saw a lot of other posts on the net with this same problem.