Should entity class hold the collection of related child records according to OO guideline?

 public class Employee
{
    public string Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

public class EmployeeHistory
{
    public string EmployeeId { get; set; }
    public string EventName { get; set; }
    public string EventDescription { get; set; }
}

Is it recommended to expose a property in the Employee class which gives collection of the EmployeeHistory records which belong to the employee? In good OO design, can such collection be part of the Employee class?

Answers


Yes. In my applications, this is an essential part of the data model. I use the navigation properties in Entity Framework to select associated data. Without it, it would be awkward to retrieve data from my data store.

Here is an example from Entity Framework (generated by a template, but this would be similar for code first):

public partial class JobDetail
{
    // constructor is here

    public int Id { get; set; }

    // properties are declared here, but redacted for brevity

    // here is the "magic" - the virtual property is replaced by a proxy 
    // to the instance of the child entity at runtime by the db context
    public virtual ICollection<DetailAttribute> Attributes { get; set; }
}

Here is the DetailAttribute class showing the link between parent and child:

public partial class DetailAttribute
{
    // constructor here...

    public int Id { get; set; }

    // other properties...

    // link to child attribute type entity
    public virtual AttributeType AttributeType { get; set; }

    // link to the parent entity
    public virtual JobDetail JobDetail { get; set; }
}

Here is an example of some code that uses a parent/child relationship in my code:

var myEntity = (from jobDetail in _ctx.JobDetails
   from attribute in jobDetail.Attributes
   where attribute.AttributeType.Name == "TestAttribute"
   select jobDetail).ToList();

Here is the SQL Code that was generated as a result:

SELECT 
    [Extent1].[JobDetailId] AS [JobDetailId]--,
    -- additional columns are here...
    FROM   [Datafeed].[JobDetail] AS [Extent1]
    INNER JOIN [Datafeed].[Attribute] AS [Extent2] ON [Extent1].[JobDetailId] = [Extent2].[JobDetailId]
    INNER JOIN [Datafeed].[AttributeType] AS [Extent3] ON [Extent2].[AttributeTypeId] = [Extent3].[AttributeTypeId]
    WHERE N'TestAttribute' = [Extent3].[AttributeTypeName]

As you can see, JobDetails has a child DetailAttribute (Attribute in the database) and DetailAttribute has a child AttributeType. I simply navigated through DetailAttribute to get the name of the AttributeType, giving me all JobDetail entities that are decorated with an attribute of type "TestAttribute".

However, you will need to be mindful of recursion during serialization (myJobDetail.Attributes[0].JobDetail.Attributes[0].JobDetail.Attributes[0]... etc.)

Take a look at this link to get an idea of how a complex data model would look:

Creating a More Complex Data Model for an ASP.NET MVC Application | The ASP.NET Site

I use database first, but this example uses code first, which is more in line with your question because it allows you more control over your object model (without the use of T4 templates).

Also, consider Lazy Loading if not using Entity Framework. This will ensure that you don't potentially load lots of EmployeeHistory entities when you just wanted a single property off of your employee. In fact, I had to add the ToList() in the example above to get Entity Framework to generate the SQL so I could post it here. It won't execute the SQL until you first need the data.


Yes it's a common pattern.

The property will probably be named history and used as:

employee.history.Add(new EmployeeHistory())


Need Your Help

How to install app from Android Studio on emulator (maybe using Gradle)?

android intellij-idea android-emulator android-studio

I'm normally testing my android app on a physical device, but today I want to do some testing using an emulator. So I created one and it's running fine. I now want to install my app on my emulator. I

Why does the 0x55555556 divide by 3 hack work?

algorithm bit-manipulation arithmetic-expressions

There is a (relatively) well known hack for dividing a 32-bit number by three. Instead of using actual expensive division, the number can be multiplied by the magic number 0x55555556, and the upper...