Bi-directional communication in nhibernate 4.0

I have some code that works fine on NHibernate 3.1, but when it fails on NHibernate 4.0

So this is the class relationship

public class Employee : BaseEntity
{
    ...
    public Department Dept { get; set; }
}

public class Department : BaseEntity
{
    ...
    public IList<Employee> Employees { get; set; }
}

      

and for display we have this

DepartmentMap : ClassMap<Department>
{
     Table("....");
     HasMany(x => x.Employees).KeyColumn("DeptId").Not.KeyNullable();
}


EmployeeMap : ClassMap<Employee>
{
     Reference(x => x.Dept).Column("DeptId");
}

      

and when i add such a worker

var dept = session.Load<Department>(deptId);
newEmployee.Dept = dept;
session.Save(newEmployee);

      

But this throws an error:

NHibernate.PropertyValueException: null-null property refers to null or transient

I read that I need to add a relation in two ways, so I changed it to

var dept = session.Load<Department>(deptId);
newEmployee.Dept = dept;
dept.Employees.Add(newEmployee);
session.Save(newEmployee);

      

But now I have this error:

NHibernate.PropertyValueException: Property value dehydration error for ... System.IndexOutOfRangeException: Invalid index 7 for this SqlParameterCollection with Count = 7.

So, I want to know how to fix it and where can I read about the changes in NHibernate about this with bi-directional

0


source to share


2 answers


I found the fix for the problem: The fix for the problem is to add the inverse to the display of the parent file. Thus, the mapping for the department will be:



DepartmentMap : ClassMap<Department>
{
     Table("....");
     HasMany(x => x.Employees).KeyColumn("DeptId").Inverse().Not.KeyNullable();
}

      

0


source


The first problem is bi-directional display

We must always appoint both sides of the relationship. Well, always?!? This is perceptual and good practice.

But , if we want to use (Department) to retrieve , we need not assign . .Load()

parent

parent.Chidren.Add()

Load()

is a clever way of getting a "bogus" (proxy) instance represented simply by the id of that object (to create a valid INSERT statement)

So in this case we should avoid dept.Employees.Add(newEmployee);

- we don't need to load the Department at all at all

// existing parent - but NHibernate just creates a proxy with expected ID
var dept = session.Load<Department>(deptId);
// child Employee is provided with parent reference - it is enough
newEmployee.Dept = dept;
// this will not help, just will execute SELECT - no benefit
// dept.Employees.Add(newEmployee);
// save and it should work
session.Save(newEmployee);

      

The second (real) problem is double mapping

Until it appears in the code snippets of the question, I would bet that Employee does have this def and display

public class Employee : BaseEntity
{
    ...
    // reference
    public virtual Department Dept { get; set; }
    // reference_ID also mapped as integer
    public virtual int? DeptId { get; set; }
}

EmployeeMap : ClassMap<Employee>
{
     Reference(x => x.Dept).Column("DeptId");
     Map(x => x.DeptId)
         // with .Not.Nullable() by code or convention
         ; 
}

      



So we have two properties in C # that belong to the same SQL column. I would say this is absolutely normal, but we have to be sure to tweak it a bit. Integer must be zero and MUST be read-only

EmployeeMap : ClassMap<Employee>
{
     Reference(x => x.Dept).Column("DeptId");
     Map(x => x.DeptId)
        .Nullable()
        .Insert(false)
        .Update(false); // as far as I rememeber syntax to replicate
      // <property name="DeptId" insert="false" update="false" not-null="false />
}

      

So what happened? what are both exceptions experienced unchanged?

NHibernate.PropertyValueException: null-null property refers to null or transient

the above issue means the expected NHibernate DeptId property will also be provided

NHibernate.PropertyValueException: Error value to dehydrate for ... System.IndexOutOfRangeException: Invalid index 7 for this SqlParameterCollection with Count = 7.

this kind of problem is usually a duplicate mapping - two properties for the ONE column. Most often because of the Reference and ID, the reference is mapped to a single column ...

Even if the problem is not directly related , I hope this gives you enough information to identify the real culprit. int? DeptId

0


source







All Articles