views:

766

answers:

2

I have the following domain classes:

public class Installation : Entity<Installation>
{        
    public virtual string Name { get; set; }
    public virtual IList<Institution> Institutions { get; set; }

    public Installation()
    {
        Institutions = new List<Institution>();
    }
}
public class Institution : Entity
{
    public virtual string Name { get; set; }
    public virtual string Address { get; set; }
    public virtual string City { get; set; }
    public virtual Installation Installation { get; set; }        
}

I have made the Entity base class according to the following post. I have the following mappings defined:

public class InstitutionMapping : ClassMap<Institution> 
{
    public InstitutionMapping()
    {
        WithTable("Institution");
        Id(i => i.Id).GeneratedBy.Guid();
        Map(i => i.Name).Not.Nullable().WithLengthOf(50);
        Map(i => i.Address).Not.Nullable().WithLengthOf(50);
        Map(i => i.City).Not.Nullable().WithLengthOf(50);
        References(i => i.Installation).ColumnName("InstallationId").Not.Nullable().WithForeignKey();
    }
}
public class InstallationMapping : ClassMap<Installation>
{
    public InstallationMapping()
    {
        WithTable("Installation");
        Id(i => i.Id).GeneratedBy.Guid();
        Map(i => i.Name).Not.Nullable().WithLengthOf(50);
        HasMany<Institution>(i => i.Institutions).KeyColumnNames.Add("InstallationId").Cascade.All();
    }
}

When I run the following code:

Installation installation = TestHelper.CreateAnonymousInstallation();
installation.Institutions.Add(TestHelper.CreateAnonymousInstitution());
installation.Institutions.Add(TestHelper.CreateAnonymousInstitution());
session.Save(installation);

I get the following error:

NHibernate.PropertyValueException: not-null property references a null or transient value.

How to overcome the problem?

Thanks in advance Lukasz Glaz

A: 

As I can see your Institution class has reference on Installation class. And this reference is set to not null. When you are creating AnonymousInstitution do you set some Installation for it?

Sly
No. I thought that as I am adding institutions to the collection it is enough and NHibernate will take care of the reference in the other direction. Is it possible to set it so I only need to do one of those: set Installation for institution or add institution to installation?
GUZ
You need to take care about association in both directions. If your Institution requires Installation and cannot exist without it you can left only one open contructor for witch will have Installation as parameter.But for NHibernate you will need to left protected constructor without parameters
Sly
I understand. I have one more problem: I am unit testing the mapping using PersistenceSpecification. When verifying mapping for the Institution CheckList method also throws NHibernate.PropertyValueException: "not-null property references a null or transient value". How to use PersistenceSpecification when I need to alter both sides of the relationship?
GUZ
A: 

I believe it's inverse=true that is needed.

HasMany<Institution>(i => i.Institutions)
   .KeyColumnNames.Add("InstallationId")
   .Cascade.All()
   .Inverse();

Or of course add a method in the installation class to handle this explicitly.

public class Installation : Entity<Installation>
{        
    public virtual string Name { get; set; }
    public virtual IList<Institution> Institutions { get; set; }

    public Installation()
    {
        Institutions = new List<Institution>();
    }

    public virtual void AddInstitution(Institution entity)
    {
        entity.Installation = this;
        Institutions.Add(entity);
    }
}
mhenrixon