How would I design classes say in c# to represents a database model?
Given the following tables and fields for a database,
Table: Employee
Pk EmpID
Lname
Fname
Adress
Fk DeptID
Table: Department
Pk DeptID
DeptName
Location
Ok so now I want to make 2 classes in C#, one for Employee and one for Department. The part I get hung up on is the foreign keys. Should I use the foreign keys in my design for the objects, or should I put a reference in my Employee class of the Department,or should I put a list of employee references in my Department class,or should I do both? I know if I use foreign keys, it will be less efficient because I will have to search through a list of primary keys that match the foreign key but I probably should include them in the design anyway.
Don't use "foreign keys" in your objects. Use references; each Department should have a list of Employees. Depending on whether or not you have a need to backreference from Employee to their Department, make the determination as to whether Employee will have a reference to Department.
Elaboration on #Paul Sonier answer...
P.S. I'm using business layer, business classes in a general sense, not as jargon of some particular technical design pattern.
The specific problems of using database keys
Using database keys is going to cause an explosion of coding overhead to keep objects and the database in synch. As the need to add, change, delete objects happens (via user GUI) you'll be jumping through hoops like crazy. How would you create a child object when the parent object does not exist yet in the database? Imagine trying to do this with any N-level data structure.
Always design business classes without regard to data storage
Business layer classes should faithfully reflect the business rules, jargon, concepts, and context. Polluting this "idea space" with non-business stuff with details about storing or displaying data is bad in the long run. Hear me now and believe me later.
Business classes based on some particular database table layout (and it's keys, etc.) is going to make it disastrously difficult to write code for validating rules, creating proper state of those objects, and so on. This is on top of the problem of keeping the object IDs in synch w/ the database.
Maximize Decoupling of Business layer and Data layer
The example shown in your question is a tempting deception. Some of your business classes may map very well to your database design. And consequently the primary and foreign keys may seem to fit as well.
BUT in any non-trivial application the database model will deviate. If not now, later. It will deviate for the purposes of database integrity, efficiency, and speed. And what does this have to do with the business model? Nothing.
Indicators that you're doing things right
You can instantiate a business object without an existing database
Each object can reference it's "children" without requiring special keys created outside the business class model.
Each business object on its own can validate, enforce, flag, etc. all of it's own rules, even trivial ones like "can't be blank". Business rule validation for composite classes/objects is class design & analysis activity - not database design activity.
First, if possible I would suggest using a tool like NHibernate, the Entity Framework, or Linq to SQL to do the object to relational mapping for you. But, if you don't want to do that, I'd probably design my object model like this:
public class Employee
{
public int Id { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public Address Address { get; set; }
public Department Department { get; set; }
}
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
public Address Location { get; set; }
public ICollection<Employee> Employees { get; set; }
}
I don't want to oversimplify but if you have navigation properties from Employee => Department or Department => Employee is pretty specific to the needs of your application.
However, as a rule of thumb, I tend to put navigation properties from the top of the heirarchy down. That means I would have Department.Employees but not Employee.Departments.
Again, this is specific to you, but it seems pretty unlikely that you would ever need to get the Department object from every single Employee. So, lookup with a key inside the Employee class something like this:
class Employee {
public int[] DepartmentIds { get; set; }
public List<Department> Departments {
get {
return YourStaticReference.DepartmentList
.Where(x => this.DepartmentIds.Contains(x.DepartmentId));
}
}
}
See? Best of luck!
Related
Let's define Term as a principal entity and Course as a one to many dependant relationship.
public class Term
{
public int Id { get; set; }
public List<Course> Courses { get; set; } = new List<Course>();
}
public class Course
{
public int Id { get; set; }
public DateTime EndDate { get; set; }
}
A common query criteria for our Term entity is to check whether all of the courses are finished or not and by that we deem the Term as finished or not too, and this implicit state can show itself in a lot of places in our bussiness logic, simple queries to populate view models, etc.
Using ORMs like EntityFramework Core this query can popup in a lot of places.
Terms.Where(t=>t.Courses.All(c=>c.EndTime > DateTime.Now))
Terms.Count(t=>t.Courses.All(c=>c.EndTime > DateTime.Now))
Other examples of this that come to mind are a product and its current inventory count, posts that only contain unconfirmed comments, etc.
What can we consider as best practice if we are to capture these implicit states and make them directly accessible in our principal entity without the need to rehydrate our dependant entity from the database too?
Some solutions that come to mind:
Using a computed column to do a subquery and map it to a property on the principal entity e.g. Term.IsFinished
Defining a normal property on our entity and use a scheduling solution to update its value on predetermined timestamps which is not acceptable in a lot of cases due to inconsistency in different intervals, or use domain events and react upon them to update the property on the principal entity
Create a view, with the two tables joined and aggregated per principal entity.
Use the view directly in Entity Framework instead of the base table.
For bonus points:
In SQL Server you can create a clustered index on the view, and it will be automatically maintained for you. Oracle has a similar concept.
In other RDBMSs, you would need to create a separate table, and maintain it yourself with triggers.
It is my first time in DDD. In company we don't have "domain master". I have only read about DDD I need to implement domain with DDD aproach.
So, I know that in domain there are no place for Database features. But if I would use my domain with Entity Framework and NOSQL database. With EF i need to make collections virtual and in constructor alloce as new. This is bad in DDD?
My code:
public abstract class Merchant : AggregateRoot
{
public Company Company { get; set; } // Entity
public string CIF { get; set; }
public string NIP { get; set; }
public string Status { get; set; }
public Address Address { get; set; } // Entity
public Group Group { get; set; } // Entity
public virtual ICollection<Brand> Brands { get; set; } // Brand is entity
protected Merchant()
{
this.Brands = new List<Brand>();
}
}
There are multiple shades of opinion about that issue in the DDD space.
To me, the primary measure of "persistence ignorance" is :
Will a change in my database break things in my domain layer, forcing
me to open up the domain model and modify stuff to fix it ?
If we look at your example, the answer is clearly no.
It would have been the case if you had for example data annotations in your entity class referring to table or column names, or if you relied on mapping by convention and changed the Merchant table name to Reseller in the DB. But having a default constructor and virtual property doesn't make your domain class more fragile in the face of database changes.
Then you have a secondary question, a less critical one IMO :
Is the ORM a hindrance in my implementing domain entities just the way I
want and as DDD-compliant as they need to be ?
This one is a bit more challenged. It might be, if the ORM forces you to add operations that can leave the domain object in an inconsistent state. I wouldn't consider a parameterless constructor as prone to that though, since it can be private and thus impossible to shoot yourself in the foot with. Same with setters.
Some consider that small traces such as the need for virtual and parameterless constructor violate DDD, because your entities are not pure any more, they contain oddities caused by the presence of an ORM. Therefore, you should create a second "persistence" model to leave the domain model untainted. I don't. I think most of the time it's not worth the tradeoff in terms of complexity - you can live with the small quirks as long as the first rule of persistence ignorance holds.
I would be more concerned about having public setters than a protected default constructor or a virtual property. The problem with that is can lead to an inconsistent state of the entity. For example, you may want to validate the address properties to make sure all the required properties are set and the postal code corresponds to the state/country. Another example would be status transitions; once the entity reaches a "final" status, it cannot be changed anymore.
While you can create separate validators for entities and use them before you persist the entities, it defeats the purpose of a rich domain model.
There are a few ways to get around it. You can create DTO objects that mirror the database schema and use hydrators to populate the entities (with protected/internal property setters) from those DTOs assuming the data in the database is always in the consistent state. All the new changes will have to go through entity methods to get validated. Then you would hydrate the DTOs based on the latest entity data and persist it.
CQRS with event sourcing is a more advanced alternative of this that persists all changes as an immutable log/event-store rather than (only) the latest data snapshot. But that is not something that is necessary for every domain scenario.
I am just trying to get out of my comfort zone of typical N-Tier architecture of Repository/Service/Presentation and have started looking at DDD with Aggregates and I have to admit I'm a little confused and was hoping someone could clarify the following example:
If I had an Entity called News, NewsImage and Customer which were all EF persist-able objects like so:
public class Customer
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
public class NewsImage
{
public virtual int Id { get; set; }
public virtual byte[] Data { get; set; }
public virtual News News { get; set; }
}
public class News
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<NewsImage> NewsImages { get; set; }
public virtual Customer Customer { get; set; }
}
As I understand it these could be the objects we would use to persist the domain objects to the database but if we are using aggregates from the domain model we could have something like this:
public class NewsAggregate
{
public int Id { get; set; }
public string Name { get; set }
public void AddImageToNews(byte[] imageData)
{
// Hide NewsImage or that object and add the byte[] data here?
}
}
My questions are following and I would appreciate any clarification as I am certain I am misunderstanding the fundamental principles here:
Only the aggregate objects should be exposed to the presentation layer (or any consuming layer).
How do I handle converting/persisting the aggregate objects to the database, I could use mapping which is fine but then how do I know if I am creating an object or updating (by whether it is transient if the Id is set or not?). How do I know if new images have been added and which to update or remove? I think the problem I am having is I call create pass a news aggregate to a Repository and create it, I could then get the aggregate back from the domain populated via the entities with EF and then add an image, when I pass the news aggregate back how do I know what has changed in order to create/update data?
Where should the customer go, should it be on the news aggregate object as an AddCustomer method, should there be a CustomerAggregate which has an AddNews method and with both of these options how to persist?
Many thanks for any insight, I've been reading around and looking at sample projects which demonstrate the concept but don't seem to fully explain best ways to achieve this.
First: DDD does not suggest you any specific architecture. I've used many different architectures with DDD and you should use what's good for the task. Obviously, if you think in a data driven way, you will encounter many problems with DDD.
DDD is a methodology designed to cope with complex business rules. You should not use it if your application value is in technological asset (as being in the cloud, exposing web services or some nice html5/mobile UI), but in the complexity of the business that it handles.
You should not use DDD for simple business rules. The rule of thumbs is: if you don't need a domain expert to understand the business, you don't need DDD at all.
Then, to properly understand aggregates, you should read the Vernon's essay on the topic.
That essay explain that aggregates exist to ensure business invariants.
You should never use aggregates just to optimize db access.
1) It depends on what capacity. There is a rule stating that aggregates can only reference other aggregates directly - not entities or value objects contained in other aggregates. This is to enforce aggregates as consistency boundaries - they fully encapsulate what they "aggregate". There should be a repository per aggregate. The presentation layer, and any outer layer, can require references to aggregates in two general capacities - for display purposes or for behavioral purposes. An aggregate shouldn't concern itself too much with how it will be displayed because queries can be implemented using a different model better suited for the task - a read-model. Instead, the aggregate should focus on behavior. And yes, in cases where the presentation layer wishes to execute a behavior on an aggregate it should reference the aggregate by its identity. Better yet, create an application service to encapsulate the domain layer and expose the behaviors as a simple facade.
Also, an aggregate is not a single class but usually a set of classes clustered around an aggregate root which is an entity. You don't necessarily need a separate class to represent the aggregate, it could just be the root entity.
2) For persistence, it seems you're using EF which should handle all change tracking for you. It should keep track of which objects are persistent or which are transient. ORMs such as NHibernate also do this.
2.1) This depends on whether Customer is itself an aggregate. If so, then News should reference Customer by ID only. Moreover, it may be that a customer is required for a news entity in which case a customer ID should be passed to the constructor of the News entity. If it is not required, then there is a behavior which associated a customer with a news entity. Consider this from the domain perspective - what is the meaning of associating a customer with a news entity? Try to move away from thinking in a technical, CRUD manner such as AddCustomer and think more in terms of the surrounding business intent.
As pointed out by Giacomo Tesio, DDD shows its value in domains with some complexity in business logic. If all your behaviors can be mapped to CRUD then leave it CRUD. Otherwise, look for behaviors in your domain instead of focusing on the data. Your entities and value objects should expose behaviors and hide state as much as possible. Do read and re-read the referenced article: Effetive Aggregate Design by Vaughn Vernon.
I have a method called GetCustomer that returns a Customer object.
Customer object is as below.
Public class Customer
{
public int Id { get; set;}
public string Name { get; set;}
public int CompanyId { get; set;}
}
Lets say Customer is related to a Company and I have to display this customer information on the screen UI. Now, when I call the GetCustomer method I only get back the details about the Customer. On the screen, I also need to display the companyname that this customer belongs to.
One easy way to do this would be to have a property called CompanyName in the customer object and fill it from your datalayer method. But I'm not sure if thats best practice. If the customer also belongs to a department, now I need to have DepartmentId and DeptName as properties. Ids are a must since sometimes I need to send the Id to get the full Dept/Company object.
I don't want to have the full objects for Department and Company in the Customer object.
I assume this is a common scenario where a particular object is linked to others using an ID and when you bring back the main object, you just need to display the name from the other linked objects.
What is the best to way to handle this. My main intention is to avoid an (or more) extra database call.
I'm NOT using Linq or Entity Framework, just regular ADO.NET.
This situation depends on your goals as;
1 - if you want to avoid extra DB calls, you have to code your UI via your db communicator with only one instance, open it only once and flush its members (adapter, command ..etc.) every time after making DB calls and close connection at the end of data transfers.
2 - for other purpose of your question, use lazy loading. put only id's on your entity and initialize and use the id's belonging entity if needed!
For example:
public class Customer
{
public int Id { get; set;}
public string Name { get; set;}
public int CompanyId { get; set;}
}
public class Company
{
public int CompanyId;
//company fields
}
// .. on your business layer if you need to use Company data:
// examine your Customer instance as "customer"
Company userCompany = GetCompanyWithId(customer.CompanyId);
but as you no doubt of your guess, data that is going to load is depends of your needs. Think simple. If your only need is Department and Company names, than you can create a view on your DB and can call it on your code. You can create an entity as CustomerWithFullData and you can put a Customer and a Department etc. in this entity and when you need to show full data you can fill this with DB View. Or dont bother to create entities. If you dont need entity, Call DB View directly DataSet and bind Tables. So you can transfer data collection work to DB and this is what we want to do.
As i said before, think simple.
What I would do is to retain an OO structure at the level of your business objects, and modify your DAL to return all the information you need with a single DB round-trip.
For example, you could have a stored procedure that returns two result sets: one for the Customers, and another for the Companies they reference. You could use table valued parameters to pass the SP a list of one or more Customers to look-up.
Depending on the size of your DB and your performance requirements, you also might be able to read the entire Customer and Company tables into memory when the app starts, cache the results, and manage insert/update/deletes against that data.
Can someone help me understand how best to model a composition relationship?
If for instance I have a student whom can have many schedules, I would create roughly:
class Student
{
prop long Pk { get; set; }
prop string Name { get; set; }
prop List<Schedule> Schedules { get; set; }
}
class Schedule
{
prop string Semester { get; set; }
prop List<Course> Courses{ get; set; }
}
Somewhere down the line I may have a Schedule object, and will wish to identify which student it belongs to. I want to be able to write Schedule.Student.Name, and receive the student's name in return. Do I add a Student property to my Schedule object as well?
My application has been passing a Student Pk to my Schedule object in order to do CRUD functionality. I'm keeping the Student PK as a private variable in order to keep a handle on it if I need it.
As my application becomes more complex, I'm finding it hard to maintain what I've been doing. What are your suggestions for me? What else can I consult (books/links) to get a refresher and better handle on these fundamentals?
"I want to be able to write Schedule.Student.Name, and receive the student's name in return. Do I add a Student property to my Schedule object as well?" Yes.
What you are describing (supporting both foreign keys for lookup and object references for easy navigation of the object graph) sounds like a really good match for an object-relational mapper (ORM). A good ORM will automatically load the associated object/objects for you using the FK/PK (e.g. if the Schedule has a StudentPK field then the mapper will handle loading/mapping of the Student property for you). There are many products of this type: you can use built-in .NET frameworks such as the Entity Framework, open-source ones such as NHibernate or commercial products such as LightSpeed, LLBLGen, EntitySpaces or OpenAccess (disclosure: I work for a company that makes a commercial ORM). Google for ORM or object-relational mapper, or check Wikipedia, for an overview of the kind of thing I'm describing.