4

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");
    }
}
Mauricio Scheffer
  • 98,863
  • 23
  • 192
  • 275
Christian Ruppert
  • 3,749
  • 5
  • 47
  • 72

3 Answers3

11

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>();
    }
}
dabide
  • 996
  • 1
  • 6
  • 18
Daniel T.
  • 37,212
  • 36
  • 139
  • 206
  • To extend support for nullable DateTime and to see how to add conventions to the configuration see [this answer](http://stackoverflow.com/a/30753122/411428). I like the `Apply()` implementation better in this answer. Note that both answers also work if you don't use automapping but have dedicated mapping classes. – Manfred Nov 29 '15 at 02:34
  • You should really use `criteria.Expect(x => x.Type == typeof(DateTime) || x.Type == typeof(DateTime?));` – Scott Whitlock Jun 14 '17 at 12:16
2

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.

Community
  • 1
  • 1
Xcalibur
  • 3,613
  • 2
  • 32
  • 26
2

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");
    }
}
Derek Ekins
  • 11,215
  • 6
  • 61
  • 71