I am googling this issue now for weeks, but cannot find a good discussion.
It boils down to this:
As POCO entities used in a dbContext are in fact a definition of the database, shouldn’t they be constrained to the Data Access Layer and not be visible outside it?
On the other hand: it is convenient to hide some POCO entities in the ViewModels. so that changed properties can be passed back easily to the Data Access Layer.
I find many examples of Entities that make their way into the user interface, but also many examples of where AutoMapper is used to map the properties of a ViewModel to an Entity.
Can someone point me to some good working examples or discussions that could help me make a well informed choice?
2
Here is one rule of thumb (but don’t follow it blindly! Understand why you must use it!) for the direction that your dependencies must follow
Always depend in the direction of abstraction and stability
What that mean is that the dependencies that everyone depend on must be dependencies that change the less. Everyone depend on them, thus they’re costly to change. So design those dependencies to have little to no reason to change!
And one way to do that is to make those dependencies mostly of unimplemented interface and stupid data structure that serve only to transfer information between objects. Then, more opinionated module, like the UI and the Data Access layer, and various part of the business logic, implements those interface with big fat objects that actually do the work. This is called the Dependency inversion principle.
Now, the direction that the arrow of the layers must take depend on who your talking to: “UI must depend on business logic which depend on the data access! No! The business logic must be in the center and everyone depends on it!” Lots of opinions and religion, but its all futile in the end. What matter is the abstraction. If your dependencies is through abstract elements, then you have it. The rest is pure pointless intellectual debate.
So, to answer your question, I’m gonna ask you another one “What are the reason for your so-called entity to change?” You have the answer in your own question :
As POCO entities used in a dbContext are in fact a definition of the database
If your entity are a definition of the database, that mean they will change everytime the database change. And if they must conform to a dbContext, that mean they have a strong coupling to the Entity Framework. If Microsoft decide to change the way EF work, your entities will have to change. Your entities will not be the nice little abstractions that you need to minimize coupling.
So yes, in that case, if you want to consider them a model of the database, then you should hide them away in a persistence layer, and make sure that nobody ever see them that don’t also know about the database.
In summary, if you want an application that is well decoupled and strongly cohesive, no, they should not be depended upon by everyone, because if you do, everyone will depend transitively on the database structure. So everytime the database change, the whole application will have to change and it will be a pain. The way people usually cope with that is to make the database not change, and that introduce a lot of rigidity in your data storage. At some point or the other the database will need to change, and you will have to pay a hefty price of technical debt at that point.
The above was as neutral as I can make it, the rest will be more opinionated. Feel free to ignore it if it don’t fit your views.
Your entities should be the base of your application and everyone should depend on them. They should not, never, be an implementation of the database. The entity framework job is to bend around your entity, and if he can’t do that, then it’s not the framework for you: ditch it as soon as you can. He shouldn’t have any power over your entity. YOU decide how your entities are structured. Don’t buy into the promise of magic that the conceptor demos are showing you. At one point or the other you will need to do something unexpected, all the magic will disappear, and you will have to leave your nice dreamy world and write the code you really needed from the start.
Try to make your entities an abstraction of your domain model (which is much less likely to change), and at that point, everyone will be able to depend on them, and your database will be free to be implemented however you want. You will have less magic at first and you will code more, but in the long shot, you will win on all account.
To properly answer this you have to consider 2 aspects: the entities themselves and the DB connection.
Naturally the DB connection should only be accessible from the data access layer, so you have a reduced surface to interact with the DB.
The entities that come from there though… obviously if you’re retrieving a read-only entity and passing around like a plain old data object, then there’s no problem, so ahead and use them knowing that you’re just bypassing the pain of creating a whole alternative layer of objects that exist to pass the entity data across tiers. I mean, you could create a new class to send data to the presentation tier, and the logic tier could take the data from the entity and populate this new class… but generally why bother when you can just pass the entity itself and save yourself a heap of trouble and performance problems copying data.
However, it gets more interesting when you need to pass data back. Here you either have persistent entities that need to be specially marshalled as special objects (ie that contain enough information to remind the DB what they are and where they came from). This starts to make things messy, and while its easy to just pass the entity about, update its fields and pass it back up the tiers to the DB, you might as well open up access to your DB to the client in that case! Here I would try to make updates occur via special methods on your logic tier that call up into the DB to modify these. This also stops the problem where you modify an entity down on the client and fail to persist it back to the DB – you can end up with a modified entity that you use, not realising that its been orphaned by other activity.
That last bit is the most important part to understand – if you use entities through your layers, you will have to pass them up and down the stack like a complex client-server model, or your data integrity can become compromised.
So all in all, I would prefer to keep the entities in the DB layer.
5
I am googling this issue now for weeks, but cannot find a good
discussion. It boils down to this: As POCO entities used in a
dbContext are in fact a definition of the database, shouldn’t they be
constrained to the Data Access Layer and not be visible outside it?
This is a complete misunderstanding of the purpose of object relational mappers and domain driven design. What you want is persistence ignorance. You shouldn’t model a database definition but the objects of your problem-domain and how they relate to and interact with each other. You shouldn’t worry about persistence at all when you design your problem domain, unless you’re trying to fight performance problems e.g.
Entities are most definitely a cross cutting concern and it is perfetcly fine to use them in every layer of the application. However, if you want to limit the modification of an entity to a certain module, you can hide the entities within the module and only publish DTO objects that are readonly to consumers outside of the module. But within the module, every layer can be allowed to work with the entity.
On the other hand: it is convenient to hide some POCO entities in the
ViewModels. so that changed properties can be passed back easily to
the Data Access Layer.
Yes it is, and if you don’t do it like that, you’ll bloat the code unecessarily and end up with a lasagna antipattern in the worst case.
1