Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / C#

Aggregate Root Pattern in C#

Rate me:
Please Sign up or sign in to vote.
4.91/5 (16 votes)
13 Nov 2015CPOL3 min read 67.1K   12   9
Aggregate root pattern in C#

Aggregate root are cluster / group of objects that are treated as a single unit of data.

I am sure lots of developers are already using this pattern unknowingly, via this short note I would like to inform you formally what you are doing.

Let us try to understand the above definition with an example. Consider the below “Customer” class which has the capability to add multiple “Address” objects to it. In order to achieve the same, we have exposed an address collection from the customer class to represent the 1 to many relationships.

C#
class Customer
{
        public string CustomerName { get; set; }
        public DateTime DateofBirth { get; set; }

        public List
Addresses { get; set; } } class Address { public string Address1 { get; set; } public string Type { get; set; } }

The above class structure works perfectly well. You can create object of customer and add multiple addresses object to it.

C#
Customer cust = new Customer();
cust.CustomerName = "Shiv koirala";
cust.DateofBirth = Convert.ToDateTime("12/03/1977");

Address Address1 = new Address();
Address1.Address1 = "India";
Address1.Type = "Home";
cust.Addresses.Add(Address1);

Address Address2 = new Address();
Address2.Address1 = "Nepal";
Address2.Type = "Home";
cust.Addresses.Add(Address2);

Now let's say we want to implement the following validations:

“Customer can only have one address of Home type”.

At this moment, the address collection is a NAKED LIST COLLECTION which is exposed directly to the client. In other words, there are no validations and restrictions on the “Add” method of the list. So you can add whatever and how much ever address objects as you wish.

C#
cust.Addresses.Add(Address2);

So how to address this problem in a clean and logical way. If you think logically, “Customer” is composed of Addressescollection, so Customer is like a main root. So rather than allowing DIRECT NAKED ACCESS to Addresses list, how about accessing the address list from the customer class. In other words, centralizing access to address objects from the customer class.

So below are three steps which I have implemented to put a centralize address validation.

Step 1: I have made the address list private. So no direct access to the collection is possible.

Step 2: Created a “Add” method in the “Customer” class for adding the “Address” object. In this add method, we have put the validation that only one “Home” type address can be added.

Step 3: Clients who want to enumerate through the address collection for them we have exposed “IEnumerable” interface.

C#
class Customer
    {
	// Code removed for clarity
        private List
_Addresses; // Step 1 :- Make list private public void Add(Address obj) // Step 2 :- Address objects added via customer { int Count=0; foreach (Address t in _Addresses) { if (t.Type == "Home") { Count++; if (Count > 1) { throw new Exception("Only one home address is allowed"); } } } _Addresses.Add(obj); } public IEnumerable
Addresses // Step 3 :- To browse use enumerator { get { return _Addresses; } } }

If you analyze the above solution closely, the customer is now the root and the address object is manipulated and retrieved via the customer class.

Why did we do this? Because “Customer” and “Address” object is one logical data unit. To maintain integrity of address validation, we need to go via the “Customer” class. In the same way loading of data, updation, deletion, etc. should all happen via the “Customer” class so that we have proper data integrity maintained.

So when we say load customer from database, all the respective address objects should also get loaded.

So when a group of objects which form one logical unit should have centralized root via which the manipulation of the contained object should happen. This kind of arrangement is terms as “Aggregate Root”.

For Further reading do watch  the below interview preparation videos and step by step video series.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect https://www.questpond.com
India India

Comments and Discussions

 
QuestionI think this way is much better Pin
Charles Schneider Pereira16-Nov-15 23:13
Charles Schneider Pereira16-Nov-15 23:13 
SuggestionIf you want to avoid people accessing your private list, one way is that you can copy it out every time when asked Pin
Song Tiansheng16-Nov-15 14:39
Song Tiansheng16-Nov-15 14:39 
GeneralRe: If you want to avoid people accessing your private list, one way is that you can copy it out every time when asked Pin
Shivprasad koirala16-Nov-15 14:47
Shivprasad koirala16-Nov-15 14:47 
GeneralRe: If you want to avoid people accessing your private list, one way is that you can copy it out every time when asked Pin
Song Tiansheng16-Nov-15 15:11
Song Tiansheng16-Nov-15 15:11 
I am agree with the point of view that Property Getter should not create a new instance every time.
A method(GetAddresses) mean it is not a light operation, then return a new List<> from it could be acceptant.

As Stewart mentioned, IEnumerable can not preventing people do a hack to casting for add new elements,

is there another way to do this preventing like code below?
public IList<Address> Addresses 
{
  get{return _addresses.AsReadOnly();}
}

Suggestion[My vote of 2] Some changes... Pin
Jono Stewart15-Nov-15 21:24
Jono Stewart15-Nov-15 21:24 
QuestionGood material, but the example could use Pin
AFell213-Nov-15 12:31
AFell213-Nov-15 12:31 
Questioni may be wrong Pin
lucwuyts13-Nov-15 10:55
lucwuyts13-Nov-15 10:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.