开发者

How do you map the Accountability pattern to SQL with NHibernate

We have implemented our domain model using the accountability pattern, which we are trying to persist using NHibernate with fluent NHibernate to define the maps.

Effectively we have 3 entities, Accountability (used to define the relationship between parties), Party (used to define the party, i.e. contact, person, business etc) and the AccountabilityType (used to specify the accountability relationship, i.e. "Belongs To", "Owned By" etc)

I am running into a brick wall in terms of defining the maps.

The ERD looks like this (aaarrgg new users cannot post images, life and its little challenges):

I hope from the maps you will be able to figure out the ERD.

The entities are defined as follows (they have been dumbed down for testing):

public class AccountabilityType
{
    public virtual string Id { get; set; }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        var other = obj as AccountabilityType;
        if (other == null)
            retu开发者_JS百科rn false;
        return other.GetHashCode() == GetHashCode();
    }
}


public class Accountability
{
    #region Properties

    public virtual Guid Id { get; set; }

    public virtual Party Parent { get; set; }

    public virtual Party Child { get; set; }

    public virtual AccountabilityType Type { get; set; }

    #endregion

    #region Methods

    public override int GetHashCode()
    {
        return Type.GetHashCode() ^ Parent.GetHashCode() ^ Child.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        var other = obj as Accountability;
        if (other == null)
            return false;
        return other.GetHashCode() == GetHashCode();
    }

    #endregion
}

public class Party
{
    public Party()
    {
        ParentAccountabilities = new List<Accountability>();
        ChildAccountabilities = new List<Accountability>();
    }

    #region Properties

    public virtual Guid Id { get; set; }

    public virtual string Name { get; set; }

    public virtual string Type { get; set; }

    // Exposed for persistence, Hackity Hack, dont hate the player hate the game
    public virtual IList<Accountability> ParentAccountabilities { get; set; }

    // Exposed for persistence, Hackity Hack, dont hate the player hate the game
    public virtual IList<Accountability> ChildAccountabilities { get; set; }

    #endregion

    #region Overrides

    public override int GetHashCode()
    {
        return Type.GetHashCode() ^ Name.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        var other = obj as Party;
        if (other == null)
            return false;
        return other.GetHashCode() == GetHashCode();
    }

    #endregion
}

And finally the fluent maps as follows:

public class AccountabilityTypeMap : ClassMap<AccountabilityType>
{
    public AccountabilityTypeMap()
    {
        Id(p => p.Id).GeneratedBy.Assigned();
    }
}

public class AccountabilityMap : ClassMap<Accountability>
{
    public AccountabilityMap()
    {
        Id(p => p.Id).GeneratedBy.Guid();

        References(p => p.Parent, "ParentId").Cascade.None();

        References(p => p.Child, "ChildId").Cascade.All();

        References(p => p.Type, "AccountabilityTypeId").Cascade.None();
    }
}

public class PartyMap : ClassMap<Party>
{
    public PartyMap()
    {
        Id(p => p.Id).GeneratedBy.Assigned();

        Map(p => p.Name);

        Map(p => p.Type);

        HasManyToMany(p => p.ChildAccountabilities)
            .Table("Accountability")
            .ParentKeyColumn("ChildId")
            .ChildKeyColumn("ParentId")
            .Cascade.All();

        HasManyToMany(p => p.ParentAccountabilities)
            .Table("Accountability")
            .ParentKeyColumn("ParentId")
            .ChildKeyColumn("ChildId")
            .Cascade.None()
            .Inverse();
    }
}

The entities are persisting to the DB, however NHibernate throws an error on session.Flush() and the error indicates that it is trying to insert an Accountability entity with a NULL id. This is first of all impossible since the Id is a non nullable Guid, and I have been through the object model to ensure that there is no object with a null/empty id.

Any suggestions would be most appreciated :)

Thanks


You can get a null if the Parent isn't being set on the Child. When a Child object is added its Parent property must be set to the parent.

consider:

var parent = new Party();
var child = new Accountability();
parent.ChildAccountabilities.Add(child);

The parent knows about the child but the child doesn't know about the parent. Try setting the parent on the child explicitly:

var parent = new Party();
var child = new Accountability();
child.Parent = parent;
parent.ChildAccountabilities.Add(child);

If that solves the problem then it just comes down to how you want to encapsulate setting the Parent property when a child is added. This blog entry might help.


It seems I got the mapping confused. I am not dealing with ManyToMany mapping since I am modeling the bridge table in my domain. The mapping should look like this.

public class AccountabilityTypeMap : ClassMap<AccountabilityType>
{
    public AccountabilityTypeMap()
    {
        Id(p => p.Id).GeneratedBy.Assigned();
    }
}

public class AccountabilityMap : ClassMap<Accountability>
{
    public AccountabilityMap()
    {
        Id(p => p.Id).GeneratedBy.Guid();

        References(p => p.Parent, "ParentId").Cascade.None();

        References(p => p.Child, "ChildId").Cascade.All();

        References(p => p.Type, "AccountabilityTypeId").Cascade.None();
    }
}

public class PartyMap : ClassMap<Party>
{
    public PartyMap()
    {
        Id(p => p.Id).GeneratedBy.Guid();

        Map(p => p.Name);

        Map(p => p.Type);

        HasMany(p => p.ChildAccountabilities)
            .KeyColumn("ParentId")
            .Inverse()
            .Cascade.All();

        HasMany(p => p.ParentAccountabilities)
            .KeyColumn("ChildId")
            .Inverse()
            .Cascade.All();
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜