Say I have two classes: Customer and Invoice. The database tables look like this:
CREATE TABLE Customer (ID int, name varchar(30), primary key (ID))
CREATE TABLE Invoice (ID int, date datetime, foreign key (CustomerID) references Customer(ID), primary key (ID))
I am trying to decide whether this relationship would be modelled using Aggregation or Association:
Aggregation
public class Customer
{
int ID;
string Name;
List<Invoice> Invoices;
public void DoSomething()
{
//Do something with Customer.Invoices
}
}
Here the customer object (including Invoices) is populated from the ORM.
Association
public class Customer
{
int ID;
string Name;
public Customer int id, string name, list<Invoice> invoices)
{
ID=id;
Name = name;
Invoices=invoices;
}
public void DoSomething(List<Invoice> Invoices)
{
//Do something with local Invoices
}
}
Say I have two user stories. One user story requires the Invoices to outlive the Customer and one user story requires the Invoice to be deleted with the Customer. How would I model this? Would I have n Invoices member (like code fragment one) and a method that accepts Invoices as an argument (like code fragment two)?
I am not developing a system that uses Customers and Invoices. I am just trying to improve my thinking.
-
1The answer depends on the concrete requirements of the application you are not developing.Stop harming Monica– Stop harming Monica2017年11月08日 16:59:42 +00:00Commented Nov 8, 2017 at 16:59
-
If an invoice can exist without a customer then the CustomerId column is NULLABLE. This is more a problem for the data mapping, not a C# class where objects are in managed memory. This would change for a language like C++ where the memory is unmanaged.Greg Burghardt– Greg Burghardt2017年11月08日 23:01:25 +00:00Commented Nov 8, 2017 at 23:01
1 Answer 1
It has to do with how you feel about delete.
In Aggregation, both the entries can survive individually which means ending one entity will not effect the other entity
When there is a composition between two entities, the composed object cannot exist without the other entity.
So if the legal team stormed the IT department with a court order and forced you to delete a customer record do you want to automatically delete the customers invoices as well, even if that's not part of the court order?
There are many reasons to delete. It's the meaning of the delete that dictates how it should cascade through the system. How will the system behave if invoices point to customers that don't exist? Is that how you want it to behave?
-
Thanks. Is there ever a scenario where you would exclude navigation properties from the domain model? For example, you have a 'Customer' and 'Invoice' table in the database, however in the domain layer Customer does not include an Invoices collection and Invoice does not include a Customer object?w0051977– w00519772017年11月08日 17:08:27 +00:00Commented Nov 8, 2017 at 17:08
-
Sure, there are things you do with customers that have nothing to do with invoices, like say a cold call sheet. Don't feel like you're only allowed to have one
Customer
class that does everything that touches the Customer table. Just use nice descriptive names so people can find stuff.candied_orange– candied_orange2017年11月08日 17:32:30 +00:00Commented Nov 8, 2017 at 17:32 -
Thanks. I guess you could have a table called CustomerInvoices and CustomerColdCallSheet etc?w0051977– w00519772017年11月08日 17:34:38 +00:00Commented Nov 8, 2017 at 17:34
-
Exactly. There is a lot of flexibility to be gained if you don't write your code as if it has to parrot what's in the database or vise versa. Write the code you need. No more. No less.candied_orange– candied_orange2017年11月08日 17:42:47 +00:00Commented Nov 8, 2017 at 17:42
-
Is it fair to say that if you have two classes that are many to many then you must use an Association rather than an Aggregate or Composition? I realise I have accepted the answer, however I can still upvote it.w0051977– w00519772017年11月20日 11:53:13 +00:00Commented Nov 20, 2017 at 11:53