Verifying datetime fluent nhibernate mappings
Asked Answered
F

3

6

I'm encountering an issue when verifying the mappings on a very simple class.

System.ApplicationException : For property 'Created' expected same element, but got different element with the same value '8/9/2011 12:07:55 AM' of type 'System.DateTime'. Tip: use a CustomEqualityComparer when creating the PersistenceSpecification object.

I have tried creating overrides for the equals and get hashcode methods and that resulted in the same error. I dug into the custom equality comparer for persistence specification testing and again hit the same error. I should perhaps take a look at this with a fresh set of eyes in the morning but I feel i'm missing something very basic.

Thanks all.

public class Blah
{
    public int Id { get;  set; }
    public DateTime Created { get; set; }
    public string Description { get; set; }
}

[Test]
public void Can_Correctly_Map_Blah()
{
    new PersistenceSpecification<Blah>(Session)
        .CheckProperty(c => c.Id, 1)
        .CheckProperty(c => c.Description, "Big Description")
        .CheckProperty(c => c.Created, System.DateTime.Now)
        .VerifyTheMappings();
}
Frederiksen answered 9/8, 2011 at 6:16 Comment(0)
R
11

You have to be careful when comparing date times because it may seem like they are the same but they can vary down to the ticks (100 nanoseconds). It's probably failing because sql server doesn't store the date times that accurately.

You'll need use a custom equality comparer such that you only compare year, month, day, hour, minute and second probably.

Take a look at this article too: Why datetime cannot compare?

Reparative answered 9/8, 2011 at 11:59 Comment(1)
Thanks Cole, I new I should have gone to bed last night and just looked at this with a fresh perspective in the morning.Frederiksen
W
5

I just ran into this while using an in-memory SQLite session. I debugged through it and noticed that the DateTimes' "Milliseconds" and "Kind" properties differed ("Utc" Kind vs. "Unspecified").

My implementation per Cole W's suggestion:

class DateTimeEqualityComparer : IEqualityComparer
{
    private TimeSpan maxDifference;

    public DateTimeEqualityComparer(TimeSpan maxDifference)
    {
        this.maxDifference = maxDifference;
    }

    public bool Equals(object x, object y)
    {
        if (x == null || y == null)
        {
            return false;
        }
        else if (x is DateTime && y is DateTime)
        {
            var dt1 = (DateTime)x;
            var dt2 = (DateTime)y;
            var duration = (dt1 - dt2).Duration();
            return duration < maxDifference;
        }
        return x.Equals(y);
    }

    public int GetHashCode(object obj)
    {
        throw new NotImplementedException();
    }
}

Your specification test becomes something like this:

var maxDifference = TimeSpan.FromSeconds(1);
...
new PersistenceSpecification<Blah>(Session)
    ...
    .CheckProperty(c => c.Created, System.DateTime.Now,
            new DateTimeEqualityComparer(maxDifference))
Whiten answered 6/8, 2012 at 20:36 Comment(0)
T
0

Simple solution is to create a new instance of the DateTime

[Test]
public void Can_Correctly_Map_Blah()
{
    new PersistenceSpecification<Blah>(Session)
        .CheckProperty(c => c.Id, 1)
        .CheckProperty(c => c.Description, "Big Description")
        .CheckProperty(c => c.Created,  new DateTime(2016, 7, 15, 3, 15, 0) )
        .VerifyTheMappings();
}
Triangulation answered 25/10, 2019 at 12:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.