Domanda

I'm learning NHibernate with Fluent. I'm trying to test mappings and one of my tests fails. Here are the entities, mappings and test class:

 public class Employee
{
    public virtual int Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string MiddleName { get; set; }
    public virtual string LastName { get; set; }
    public virtual DateTime DateOfBirth { get; set; }     
    public virtual string Gender { get; set; }
    public virtual long Pesel { get; set; }      
    public virtual DateTime CreateDate { get; set; }        
    public virtual Address HomeAddress { get; set; }
    public virtual Address BusinessAddress { get; set; }
}
 public class Address
{
    public virtual int Id { get; set; }
    public virtual string Street { get; set; }
    public virtual string BuildingNumber { get; set; }
    public virtual string FlatNumber { get; set; }
    public virtual string Postocde { get; set; }
    public virtual string Town { get; set; }
    public virtual string Province { get; set; }
    public virtual string Country { get; set; }

    public virtual ICollection<Employee> EmployeeHomeAddresses { get; set; }
    public virtual ICollection<Employee> EmployeeBusinessAddresses { get; set; }
}

public class EmployeeMap : ClassMap<Employee>
{
    public EmployeeMap()
    {
        Table("Employee");

        Id(x => x.Id, "Id").GeneratedBy.Identity();

        Map(x => x.FirstName, "FirstName");
        Map(x => x.MiddleName, "MiddleName");
        Map(x => x.LastName, "LastName");
        Map(x => x.DateOfBirth, "DateOfBirth");
        Map(x => x.Gender, "Gender");
        Map(x => x.Pesel, "PESEL");
        Map(x => x.CreateDate, "CreateDate");
        References(x => x.HomeAddress, "HomeAddressId");
        References(x => x.BusinessAddress, "BusinnessAddressId");
    }    
}
public class AddressMap : ClassMap<Address>
    {
        public AddressMap()
        {
            Table("Address");

            Id(x => x.Id).GeneratedBy.Identity();

            Map(x => x.Street, "Street");
            Map(x => x.BuildingNumber, "BuildingNumber");
            Map(x => x.FlatNumber, "FlatNumber");
            Map(x => x.Town, "Town");
            Map(x => x.Postocde, "Postcode");
            Map(x => x.Province, "Province");
            Map(x => x.Country, "Country");

            HasMany(x => x.EmployeeHomeAddresses).KeyColumn("Id");
            HasMany(x => x.EmployeeBusinessAddresses).KeyColumn("Id");

        }
    }

[Test]
        public void CanCorrectlyMapEmplyee()
        {

            var homeAddress = new Address()
            {                     
                Street = "Test street 1",
                BuildingNumber = "20",
                FlatNumber = "2",
                Postocde = "11111",
                Town = "London",
                Province = "Some UK County",
                Country = "UK"                               
            };

            session.SaveOrUpdate(homeAddress);

            var businessAddress = new Address()
            {          
                Street = "Test street 2",
                BuildingNumber = "20",
                FlatNumber = "3",
                Postocde = "22222",
                Town = "Cracow",
                Province = "Malopolskie",
                Country = "Poland"
            };

            session.SaveOrUpdate(businessAddress);

            new PersistenceSpecification<Core.Model.Employee>(session)                
                .CheckProperty(x => x.FirstName, "Greg")
                .CheckProperty(x => x.LastName, "T")
                .CheckProperty(x => x.Gender, "M")
                .CheckProperty(x => x.DateOfBirth, DateTime.Now.TruncateToSeconds())
                .CheckProperty(x => x.Pesel, "12345678910")
                .CheckProperty(x => x.CreateDate, DateTime.Now.TruncateToSeconds())
                .CheckProperty(x => x.HomeAddress, homeAddress)
                .CheckProperty(x => x.BusinessAddress, businessAddress)
                .VerifyTheMappings();
        }

This test fails. Error message: For property 'HomeAddress' expected same element, but got different element of type 'SalesMaster.Core.Model.Address'. I tried with CheckReference instead of CheckProperty for foreign keys but it gives me the same error. Address test with the same values I put for HomeAddress passes.

This test had passed before I added foreign keys. Where's the problem?

È stato utile?

Soluzione

I think that the problem is in your HasMany mappings :

HasMany(x => x.EmployeeHomeAddresses).KeyColumn("Id");
HasMany(x => x.EmployeeBusinessAddresses).KeyColumn("Id");

I personally think this is a little misleading, but the KeyColumn function expects the name of the Foreign key column in the Employee table. So it becomes this :

HasMany(x => x.EmployeeHomeAddresses).KeyColumn("HomeAddressId");
HasMany(x => x.EmployeeBusinessAddresses).KeyColumn("BusinessAddressId");

Note that those HasMany relationships aren't actually needed for your mapping to work, so unless you really need to get a list of employees living at a specific address (which is weird), you could remove them completely and only keep your References mappings.

EDIT : Finally it seems that this error occurs because you need to override Equals and GetHashCode in your Address class. When Equals is not overridden, it only returns True if the two objects are exactly the same, and NHibernate modifies your entity when you call SaveOrUpdate to turn it into a proxy, which is the default behavior. See this question for more info.

public override bool Equals(object obj)
{
    if(ReferenceEquals(obj, this))
        return true;

    var addr = obj as Address;
    if(addr == null)
        return false;

    return addr.Country == this.Country && addr.State == this.State //and so on..
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top