AdFactum ObjectMapper .NET Blog

Official blog of the AdFactum ObjectMapper .NET

Best practice for designing compositions, aggregations and associations between entities.

Posted by Gerhard Stephan on February 4th, 2008

Designing the data model can be a complex task. Specially if you think about how to bind entities together. You can bind entities together by using an composition, an aggregation or by creating an association between them. But what is the difference? And how does this affect the design of the data model?

In this post, I want to clarify the difference between composition, aggregation and association, and to show the difference of implementation. The definitions are taken from the Wikipedia.org (http://en.wikipedia.org/wiki/Class_diagram#Association)

Definitions:

Composition is a stronger variant of the "has a" or association relationship; composition is more specific than aggregation. Composition has a strong life cycle dependency between instances of the container class and instances of the contained class(es): If the container is destroyed, every instance that it contains is destroyed as well.

Aggregation is a variant of the "has a" or association relationship; aggregation is more specific than association. Aggregation can occur when a class is a collection or container of other classes, but where the contained classes do not have a strong life cycle dependency on the container–essentially, if the container is destroyed, its contents are not.

An Association can be named, and the ends of an association can be adorned with role names, ownership indicators, multiplicity, visibility, and other properties. There are five different types of association. Bi-directional and uni-directional associations are the most common ones. For instance, a flight class is associated with a plane class bi-directionally. Associations can only be shown on class diagrams.

What does this mean to the data model design?

Compositions and Aggregations are the strongest relationships. E.g. if you think of an Employee, the employee owns a work time model. If the employee will be fired, his work time modell will be deleted as well.

In that case you would directly place the work time model into the users entity. This has the advantage, that you can directly deep load the user, change the work model composition and store the changes to database.

    public class Employee : ValueObject

    {

        private WorkTimeModel worktimeModel;

 

        /// <summary>

        /// Gets or sets the worktime model.

        /// </summary>

        /// <value>The worktime model.</value>

        public WorkTimeModel WorktimeModel

        {

            get { return worktimeModel; }

            set { worktimeModel = value; }

        }

    }

 

In case of compositions you can delete the depending work time model directly when removing the employee from database. Therefore you can call the mothod : DeleteRecursive

Now back to our example. Think of a time entry. A time entry is always associated to an employee, but it does not own the employee. That mean, it does not aggregate the employee. If you delete a time entry, the user won’t be deleted. In that case it’s better to use a loose couple between the class TimeEntry and Employee.

    public class TimeEntry : ValueObject

    {

        private Guid employeeId;

 

        /// <summary>

        /// Gets or sets the employeeId.

        /// </summary>

        /// <value>The employeeId.</value>

        [ForeignKey(typeof(Employee), "Id")]

        public Guid EmployeeId

        {

            get { return employeeId; }

            set { employeeId = value; }

        }

    }

 

The [ForeignKey] attribute ensures, that the stored Property uses a foreign key to the Employee table. If you still need further informations of the employee who is associated, you can use a VirtualLink to join the employee table to the Time Entry.

    public class TimeEntry : ValueObject

    {

        private Guid employeeId;

        private string name;

 

        /// <summary>

        /// Gets or sets the employeeId.

        /// </summary>

        /// <value>The employeeId.</value>

        [ForeignKey(typeof(Employee), "Id")]

        public Guid EmployeeId

        {

            get { return employeeId; }

            set { employeeId = value; }

        }

 

        /// <summary>

        /// Gets or sets the name of the employee.

        /// </summary>

        /// <value>The name.</value>

        [VirtualLink(typeof(Employee), "Id", "Name", "EmployeeId")]

        public string Name

        {

            get { return name; }

            set { name = value; }

        }

    }

Conclusion

If you use this pattern in all your entities, you can load the entities most times without specifiing an hierarchy level. The advantage are more clearly designed business components that are much easier to understand.

I wish you a successfull time.

Cheers
 – Gerhard

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>