views:

357

answers:

2

I am currently working on a college project in which we are using Fluent NHibernate. I am working on figuring how to create testing for our entities and Fluent mappings.

I have, however, hit a dead end while trying to figure how to use the CheckList of PersistenceSpecification.

The unit test fails with the following error:

MvcShop.Core.Tests.EntitiesTests.ItemTest.CanMapItem threw exception:  NHibernate.PropertyValueException: not-null property references a null or transient valueMvcShop.Core.Entities.ItemPicture.Item.

The test is defined as:

private IList<ItemPicture> _itemPictures = new List<ItemPicture>()
{
new ItemPicture { Filename = "test.jpg", Title = "Test title", PrimaryPicture = true},
        new ItemPicture { Filename = "test2.jpg", Title = "Test title 2" }
    };

    [TestMethod]
    public void CanMapItem()
    {
        new PersistenceSpecification<Item>(Session)
            .CheckProperty(i => i.Title, "Test item")
            .CheckProperty(i => i.Description, "Test description")
            .CheckProperty(i => i.SalesPrice, (decimal)0.0)
            .CheckList(i => i.ItemPictures, _itemPictures) // Complains that Item on ItemPicture is null.
            .VerifyTheMappings();
    }

My mappings are defined as:

public ItemMap()
    {
        Table("Item");
        Id(i => i.ItemID).GeneratedBy.Identity().Column("Item_id");
        Map(i => i.ItemNo).Nullable().Length(30);
        Map(i => i.Title).Not.Nullable().Length(250);
        Map(i => i.Description).Nullable();
        Map(i => i.SalesPrice).Not.Nullable().Precision(18);
        Map(i => i.AverageRating).Precision(18).Nullable();
        Map(i => i.Visible).Not.Nullable();
        Map(i => i.Weight).Not.Nullable().Precision(18);
        Map(i => i.TimesPurchased);
        Map(i => i.InStock).Not.Nullable();
        Map(i => i.DateAdded).Not.Nullable();
        HasManyToMany(i => i.ItemCategories).Cascade.All().Inverse().Table("ItemCategoryItem");
        HasMany(i => i.ItemPictures).Cascade.AllDeleteOrphan().Inverse().LazyLoad();
        HasMany(i => i.Comments).Cascade.AllDeleteOrphan().Inverse().LazyLoad();
        HasMany(i => i.Ratings).Inverse().LazyLoad();
    }

public ItemPictureMap()
    {
        Table("ItemPicture");
        Id(i => i.ItemPictureID).GeneratedBy.Identity().Column("ItemPicture_id");
        Map(i => i.Title).Nullable();
        Map(i => i.Filename).Not.Nullable();
        Map(i => i.PrimaryPicture).Not.Nullable();
        References(i => i.Item).Not.Nullable().Column("Item_id");
    }

I really can't figure how I can populate the Item property of ItemPicture when using the PersistenceSpecification class.

Any ideas?

Best Regards, Kenneth, Denmark

A: 

You can't you need to override GetHashCode and Equals and create your own IEqualityComparer. The reason for this is that entities can't be compared by default whilst value object can.

DateTime for instance cannot be compared by default for the simple reason that they are not a value they are an instance with a value and there for datetime1 != datetime2 even if their dates are exactly the same so what you need to do is compare them on key values. For a class like above. I suppose that Item contains a bunch of ItemPictures and then in your IEqualityComparer implementation when you override equals you should check if the current object is of type ItemPicture and if it is check if the current ItemPicture's id match the other sides ItemPicture.Id. Since code speaks louder than words I'll give you a small example:

[TestMethod]
public void CanMapItem()
{
    new PersistenceSpecification<Item>(Session, new CustomIEqualityComparer())
     .CheckProperty(i => i.Title, "Test item")
     .CheckProperty(i => i.Description, "Test description")
     .CheckProperty(i => i.SalesPrice, (decimal)0.0)
     .CheckList(i => i.ItemPictures, _itemPictures) // Complains that Item on ItemPicture is null.
     .VerifyTheMappings();
}


public class CustomIEqualityComparer: IEqualityComparer
{
    public bool Equals(object x, object y)
    {
        if (x == null || y == null)
        {
            return false;
        }
        if (x is ItemPicture && y is ItemPicture)
        {
            return ((ItemPicture) x).Id == ((ItemPicture) y).Id;
        }
        if(x is DateTime && y is DateTime)
        {
      return ((DateTime)x).Year ==((DateTime)y).Year;
        }
        return x.Equals(y);
    }

    public int GetHashCode(object obj)
    {
        throw new NotImplementedException();
    }
}
mhenrixon
+2  A: 

That makes sense, thank you.

I do not believe it is the cause of the problem, however. I.e. it does not work even with the CustomIEqualityComparer. I still believe the error is due to the fact that Item on ItemPicture is not populated and the mapping says it cannot be null.

Kenneth Fuglsang
anyone found a solution?? and how do i bump up this question?
Amith George