Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map foreign key in Fluent NHibernate without object property

My question is, is there a possible Fluent NHibernate mapping for Parent and Child objects that does not require the Child object to have a Parent object property? I haven't figured out how to map the reference back to the Parent. When I call Create with the mappings as-is, I get an exception because the Child object does not have the required foreign key (required in the data store) back to the Parent.

I have two POCO classes:

public class Parent
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Child> Childs { get; set; }
}

public class Child
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual int ParentId { get; set; }
}

And some mappings:

public class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        this.Table("Parents");
        this.Id(x => x.Id);
        this.Map(x => x.Name);
        this.HasMany(x => x.Childs).KeyColumn("ChildId").Cascade.AllDeleteOrphan();
    }
}

public class ChildMap : ClassMap<Child>
{
    public ChildMap()
    {
        this.Table("Childs");
        this.Id(x => x.Id);
        this.Map(x => x.Name);
        // Needs some sort of mapping back to the Parent for "Child.ParentId"
    }
}

And Create method:

public Parent Create(Parent t)
{
    using (this.session.BeginTransaction())
    {
        this.session.Save(t);
        this.session.Transaction.Commit();
    }
    return t;
}

I want to be able to create a Parent object that has a list of Child objects, but not have the Child objects have references back to their Parent (other than the Parent ID). I want to do this to avoid the circular reference from Parent to a list of Childs back to the Parent object, since that is causing issues with JSON serialization.

like image 629
Annie B Avatar asked Jul 13 '13 02:07

Annie B


1 Answers

You can map these entities without problem, try this:

public class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        this.Table("Parents");
        this.Id(x => x.Id);
        this.Map(x => x.Name);
        this.HasMany(x => x.Childs).KeyColumn("ChildId").Cascade.AllDeleteOrphan();
    }
}

public class ChildMap : ClassMap<Child>
{
    public ChildMap()
    {
        this.Table("Childs");
        this.Id(x => x.Id);
        this.Map(x => x.Name);
        this.Map(x => x.ParentId);
        // if you have a reference of Parent object, you could map as a reference, for sample:
        this.References(x => x.Parent).Column("ParentId");
    }
}

When you get entities from ISession, do not serialize it to some format because these can be proxies of nhibernate instead entities objects. Try to create DTO (Data Transfer Object) classes and convert these entities to a DTO object, and serialize it. You will avoid circular references. For sample:

public class ParentDTO
{   
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }

    /* here you just have the primitive types or other DTOs, 
       do not reference any Entity type*/
}

And when you need to read the values to share the serialized value:

var dto = ISession.Query<Parent>()
                  .Select(x => 
                      new ParentDTO() { 
                           Id = x.Id, 
                           Name = x.Name, 
                           ParentId = x.ParentId)
                  .ToList();

Get this result from the Data Access Layer and try to serialize, for sample:

var result = Serialize(dto);
like image 71
Felipe Oriani Avatar answered Nov 18 '22 17:11

Felipe Oriani