Using a reference as id in fluentnhibernate
Asked Answered
Q

3

7

I have a child table containing an id to the parent. This is a one to one mapping, but the child table might be missing values. I'm having problems mapping this without getting an error though... I've tried several things; mapping the same column, having distinct properties etc..

Parent table
  int id

Child table
  int parentid

Parent class
  int id

Child class
  Parent parent // note I'm referencing parent, not using an int id..

Mapping

Id(x => x.Parent)
  .Column("parentid"); // fails

Id(x => x.Parent.Id)
  .Column("parentid"); // fails

References(x => x.Parent)
  .Column("parentid"); // fails - missing id

// Adding an id field in addition to parent for
// child class (id is then the same as parent.id)
// fails on save
Id( x => x.Id ) 
  .Column("parentid");
References(x => x.Parent)
  .Column("parentid");

I would like the child class not to have a distinct Id field, but rather only a reference to parent as there can never be a child without a parent. In the database however, I want to just store the parent's id.

Any ideas how I might do this?

Quigley answered 3/9, 2010 at 10:7 Comment(0)
Q
5

The following works:

Id(x => x.Parent.Id).Column("MemberID");
References(x => x.Parent).Column("MemberID").ReadOnly();

The ReadOnly for the reference is important to not get an exception

EDIT: Wasn't so simple...

My child class still had the Id property being called. Seems the Id reference for Parent.Id confuses nhibernate, and it tries to call child.Id instead. I added the following to child, and now it seems to work.. A pretty ugly hack though.

public virtual int Id {
    get { return Parent.Id; }
    set { Debug.Assert(value == Parent.Id); }
}
Quigley answered 3/9, 2010 at 11:13 Comment(1)
+1 Worked for me here, but there is a more elegant way to do so?Patsis
E
0

FluentNHibernate's API has changed over the years so I'm not sure if this syntax was available when this question was originally asked but you can now use a reference as an id if you map it as a composite id. I wouldn't call this a hack but it is a little strange that you have to map the reference to the parent entity as part of a composite id. Here's a full example:

public class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        Table( "StackOverflowExamples.dbo.Parent" );

        Id( x => x.ParentId );
        Map( x => x.FirstName );
        Map( x => x.LastName );
    }
}

public class OnlyChildOfParentMap : ClassMap<OnlyChildOfParent>
{
    public OnlyChildOfParentMap()
    {
        Table( "StackOverflowExamples.dbo.OnlyChildOfParent" );

        CompositeId().KeyReference( x => x.Parent, "ParentId" );
        Map( x => x.SomeStuff );
        Map( x => x.SomeOtherStuff );
    }
}

public class Parent
{
    public virtual int ParentId { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
}

public class OnlyChildOfParent
{
    public virtual Parent Parent { get; set; }
    public virtual string SomeStuff { get; set; }
    public virtual string SomeOtherStuff { get; set; }

    #region Overrides

    public override bool Equals( object obj )
    {
        if ( obj == null || GetType() != obj.GetType() )
            return false;

        var child = obj as OnlyChildOfParent;

        if ( child != null && child.Parent != null )
        {
            return child.Parent.ParentId == Parent.ParentId;
        }

        return false;
    }

    public override int GetHashCode()
    {
        return Parent.ParentId;
    }

    #endregion Overrides
}
Exchequer answered 22/7, 2013 at 6:18 Comment(0)
D
0

Maybe this post can help.
I've used the annotation .Cascade.SaveUpdate().
My case was with a hasone in the parent putting the annotation on both sides

Obs: Language PT-BR

Duro answered 17/9, 2015 at 14:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.