Domain driven design aggregate and Entity Framework

We discussed on how aggregates are used as a root class to work with a group of classes in Domain driven design . As we noticed, in some scenarios we need to hide details from user and let them communicate with some classes through the aggregate root only.


This works well. The problem occurs when we bring the Entity Framework into consideration.
By using Entity Framework,You can have ICollection properties for one to many relations. The thing is: “when using domain driven design, You are not allowed to work with these ICollections!”.

lets dive into it a bit more.

I give you and old “student-teacher” example. We have 2 classes: Student and Teacher. Each teacher has many students:

    public class Teacher
    {
        public Teacher()
        {
            PrivateStudents = new List<Student>();
        }
        public Guid ID { get; set; }
        public string Name { get; set; }

        //This collection is set to private so user can not access it out of the class.
        //Yet EF can access private properties.
        private ICollection<Student> PrivateStudents { get; set; }
    }

    public class Student
    {
        //The constructor is set to INTERNAL so the users of this layer, can not create an instance of it
        internal Student()
        {

        }
        public Guid ID { get; set; }
        public string Name { get; set; }
        public Teacher Teacher { get; set; }
    }

As you can see the Student constructor is internal. So other layers can not instantiate it. Because a user is not allowed to communicate with student straightly. One must communicate with “Student” through “Teacher” which is an aggregate root. Thus we need some extra methods to add and remove students in the Teacher class. In addition to that, Users are not allowed to use the ICollection properties directly. So I changed that property private. The class now looks like this:

    public class Teacher
    {
        public Teacher()
        {
            PrivateStudents = new List<Student>();
        }
        public Guid ID { get; set; }
        public string Name { get; set; }

        //This collection is set to private so user can not access it out of the class.
        //Yet EF can access private properties.
        private ICollection<Student> PrivateStudents { get; set; }
        public IReadOnlyCollection<Student> Students
        {
            get
            {
                return PrivateStudents.ToList().AsReadOnly();
            }
        }


        //Methods
        public void AddStudent(string studentName)
        {
            Student std = new Student()
            {
                ID=Guid.NewGuid(),
                Name = studentName,
                Teacher = this
            };

            this.PrivateStudents.Add(std);
        }       
    }

The trick is I have added two IReadOnlyCollection properties to the class. This way, Users of the class can see a list of students but they can not edit it. They have to edit it, through methods of Teacher class. Now you can do what ever you like in the Methods.

So, in summary, All you have to do is to identify the aggregate root class. Give it private properties for the sub classes (Like students).

Add extra methods to the class to it can work with it’s own properties.

Here you can download the source code.

Please let me know your ideas about this approach. Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *