DDD principles and repositories with Dapper - c#

I'm setting up a solution in which I apply onion architecture and DDD patterns.
One of the DDD principles encourages domain entities to have only private setters and a private default constructor, to make sure you cannot create domain entities in an invalid state.
Repositories contain the data operations on domain entities, which are mapped from/to the database. I have been trying the following two approaches:
Domain entities in a purist way: no default constructor, no public setters; validation is done in the constructor(s); which makes sure you cannot create a domain entity in an invalid state. The side effect is that it's harder to dematerialize them in the repositories in read operations; as you need reflection in order to be able to create instances and map properties; and the use of dynamics in the Dapper requests which need to be mapped to the actual domain entities. If I would map this directly to the domain entities without the use of dynamics, Dapper throws an exception that there is no public constructor.
Domain entities in a non-purist way: you allow a default constructor, and all setters are public; so you can create entities that are not valid at a given point in time. In that case you need to call the Validate() method manually, to make sure they are valid before you continue. This makes dematerilizing in the repositories much easier, as you don't need reflection nor dynamics to map the database to the model.
Both methods work, however, with option 2 the repositories become a lot simpler because they contain a lot less custom mapping code, and without reflection obviously will be more performant as well. Of course, DDD is not applied in a purist way.
Before a decide what I will use in my project, a question: are there any other micro-ORM frameworks out there that can handle private constructors and setters, so that mapping the database to those kind of 'pure' domain entities is supported without additional custom mapping logic? (No EF nor NHibernate, I want something lightweight).
Or other technial solutions to keep the 'pure' model entity approach in combination with easy repository mapping?
EDIT: the solution I implemented was the following.
First, constructors and setters in the domain entities are all 'internal', which means they cannot be set by the consumers of the domain model. However, I use 'InternalsVisibleTo' to allow the data access layer to access them directly, so this means that dematerializing from the database is very easy with Dapper (no need for intermediate models). From the application layer, I can only use domain methods to change the domain entity, not the properties directly.
Second, to construct new domein entities from my application layer, I added fluent builders to help building domain entities, so I can now construct them like:
User user = new UserBuilder()
.WithSubjectId("045454857451245")
.WithDisplayName("Bobby Vinton")
.WithLinkedAccount("Facebook", la => la.WithProviderSubjectId("1548787788877").WithEmailAddress("bobby1#gmail.com"))
.WithLinkedAccount("Microsoft", la => la.WithProviderSubjectId("54546545646").WithEmailAddress("bobby2#gmail.com"))
When the builder 'builds' the entity, validation is done as well, so you can never create an entity in an invalid state.

One of the DDD principles encourages domain entities to have only private setters and a private default constructor, to make sure you cannot create domain entities in an invalid state.
That's not quite right. Yes, rich domain models don't usually expose setters, but that is because they don't need setters. You tell the model what to do at a higher level of abstraction, and allow it to determine how its own data structures should be modified.
Similarly, there are often cases where it makes sense to expose the default constructor: if you think of an aggregate as a finite state machine, then the default constructor is a way to initialize the aggregate in its "start" state.
So normally you reconstitute an aggregate in one of two ways: either you initialize it in its default state, and then send it a bunch of messages, or you use the Factory pattern, as described in the blue book.
this means an extra mapping in between, which makes code more complex
Perhaps, but it also ensures that your domain code is less dependent on ORM magic. In particular, it means that your domain logic can be operating on a different data structure than what is used to make persistence "easy".
But it isn't free -- you have to describe in code how to get values out of the aggregate root and back into the database (or into the ORM entity, acting as a proxy for the database).

The key is that you don't use Dapper to work with your domain entities, but instead you use it inside your repository layer with POCO entities. Your repository methods will return Domain entities by converting the POCO entities (that Dapper uses for data access) to Domain entities.

Related

How do I return a domain object from the repository when there is a separate data model?

Update
My research is telling me that I should be using a Data Mapper: https://martinfowler.com/eaaCatalog/dataMapper.html. Are Data Mappers injected into repositories like this: http://www.rantdriven.com/post/2009/09/01/Using-the-Repository-Pattern-with-the-Command-and-DataMapper-Patterns.aspx and this: Repository and Data Mapper pattern or are they used as an alternative to a repository? All the examples I find seem to use Data Mappers to map DataReader objects to lists of domain objects. I am wanting to map Persistent objects to Domain objects.
Original Question
I am trying to build a Domain Model that is completely isolated from the Data Model after reading articles like this:
http://blog.sapiensworks.com/post/2012/04/07/Just-Stop-It!-The-Domain-Model-Is-Not-The-Persistence-Model.aspx. There are only six of us working on this system at the moment, however this could increase in future to 9+. However, I am beginning to think that this is not the right approach. I read a lot of questions on here, which appear to tell me to map the ORM directly to the Domain Model.
I recently asked this question: https://softwareengineering.stackexchange.com/questions/365643/should-the-data-model-be-identical-to-the-domain-model-for-mapping-purposes. One of the answerers says: "I believe the mapping in between both should be within a (persistence-oriented) repository". How do you do this mapping? I don't believe I should be using AutoMapper in the repository because of the reasons stated here: Repository pattern and mapping between domain models and Entity Framework and here: http://enterprisecraftsmanship.com/2016/02/08/specification-pattern-c-implementation/ i.e. I cannot simply do this in the repository:
public Customer getId()
{
CustomerData customerData = customerRepository.getById(id);
return Mapper.Map<CustomerDomain>(customerData);
}
I cannot do this because the invariants of the domain object will not be considered. How can I return a domain object from the repository. Do I inject a factory into the repository, which will take parameters from the data model and return a domain model? Is this even the right approach or is there another pattern for mapping data objects to domain objects?
Quick review of repositories, as defined by Evans
REPOSITORIES (provide) the means of finding and retrieving persistent objects while encapsulating the immense infrastructure involved.
(REPOSITORIES) provide the illusion of an in memory collection...
So, the API interface should normally be expressed in a domain specific vocabulary; neither the application layer nor the domain model should need to know any specifics beyond what is expressed in the API.
Commonly, the immense infrastructure means a domain agnostic persistence appliance; we don't persist domain objects, we persist bytes. With some appliances, we work very closely with the byte representation -- think streaming data to and from files. In other cases, the appliance provides a abstraction of those bytes - an RDBMS gives us an API that understands rows in tables, and encapsulates the details of how the bytes are arranged.
What this means is that somewhere we need a transformation from a domain agnostic representation to a domain specific representation, and vice versa.
Normally, these take the form of functions.
toDomainModel: JsonDocument -> DomainModel
toJson: DomainModel -> JsonDocument
These functions are normally defined by, and invoked by, the repository implementation -- they are part of the immense infrastructure that Evans describes.
I cannot do this because the invariants of the domain object will not be considered.
There are a couple possibilities here.
One, of course, would be to get a smarter mapper.
A second possibility is to model the unvalidated representation of the model as a distinct thing from a validated representation.
Example: consider a model for Money, that requires an Amount and a CurrencyCode; and the semantics of your model requires that Amount be a positive number and CurrencyCode be an entry in a fixed collection of tokens. There's nothing wrong with having an UnvalidatedMoney type, that has no semantic restrictions, and a function that converts UnvalidatedMoney to Money (enforcing the invariant).
This is analogous to what Scott Wlaschin describes for modeling a verified email address.
Note that this isn't necessarily an undue burden; if you have an invariant on some domain concept like money, you probably already have validation to do when passing new input from the world into your model. So the work is mostly about making that validation element re-usable.
A third possibility is to look into the Builder pattern. Persistent objects are, from one point of view, messages that a model wrote in the past so that it could read it in the future. So it is often the case that looking at common messaging patterns is useful.
In this approach, we would load an instance of the builder (created for us by a factory, implemented by the domain model), which has an API that allows the repository to pass the domain agnostic data to the domain model. Again, the message builder, being provided by the domain model, knows the domain invariant and can validate it.
All the validation for the domain object is done in the constructor. Should I just inject a factory into the repository?
That should be fine. You'll want to keep the coupling as small a you can manage (think interface), and you'll want to think about the fact that the factory is now part of the public API for the model (think about how to change the factory so that it remains backwards compatible).
ORM and Data Mapper
Most .NET ORM frameworks use a data mapper internally, or can be considered a kind of data mapper themselves. Some ORMs in other tech stacks may use the alternative approach to mapping: Active Record. The difference between the two is that in Active Record, the business class knows how to persist itself while a Data Mapper makes it agnostic from any persistence mechanism.
This is a different distinction than the one between having a Data Model + a Domain Model and mapping straight to the Domain Model. Regardless if you map directly to the Domain or if you have an intermediate Data Model, you will always have a Data Mapper. Both approaches imply it. The Data Mapper can be an ORM tool or custom code.
It's not clear from your question if you intend to use both an ORM and an additional Data Mapper on top, but I wouldn't recommend trying that or calling your Data Model <=> Domain Model mapping logic a "Data Mapper" in the PoEAA sense of the term.
Object hydration and invariants
Oftentimes, domain object hydration by a Data Mapper goes through another path than normal use-case driven code in order to bypass all validation that would otherwise happen. This can be done via parameterless constructors with restricted scope (protected, internal with internalsVisibleTo) that the ORM or custom code will have access to. Some newer reflection-based frameworks can also access private fields.
With a Data Model in addition to your Domain Model, this is all simpler since you don't need to restrict access to a Data Model object the way you would a Domain entity. Data Models don't have invariants, you can safely leave their parameterless constructor and properties publicly accessible and settable for rehydration. The only thing you need to take care of is have some FromData() method or constructor on your domain entity that takes a data model as an input and instantiates the entity. Again, the technique is made safe thanks to accessibility level restriction - the hydration code can typically be in an assembly granted internalsVisibleTo by the domain.

EF's POCO vs POCO better Data transfer Object?

I have a scenario in which I have some custom entities being used in a system (desktop) bound to its UI. I have shifted to Entity framework for the benefits it provides but the will continue to use the custom entities to bring data from UI as the custom entities are tightly coupled with the system.
Now if I want to remove the dependence of the system on these custom entities like say I want to use my services from the web or any other platform what are my options from design perspective?
I think that to remove dependence on custom entities I will have to use a Data Transfer Object say POCO.
So should I use the POCO entities that EF provides for this purpose or write them separately??
Does it make sense. What should be my approach.
Even if domain objects are implemented as POCO they're still domain objects and shouldn't be transfered to other physical tiers without using a DTO.
Think Entity Framework entities are proxies of your POCO-style domain objects in order to - for example - inject change tracking and lazy-loading. Also, a domain object might contain more data than required in some parts of your UI.
For example, you've implemented a grid with 3 columns: name, second name and age. You bind user profiles to the so-called grid, but your Profile domain object has also more properties, and this will transfer more data than required by your 3-columns-grid!
That's why you'll want to keep your domain in your domain, and data emitted by your services will serialize DTOs to cover your actual UI use cases and you won't be transferring fat objects over the wire, which might add extra costs to your organization (usually you pay for network usage in hosting environments), and obviously, serializing small objects is less intensive, isn't it?
A clean architecture will have a class library assembly (let's call it Common) containing your POCO objects. As per definition, POCO objects are persistence ignorant and contain no behaviour. They just represent your entities.
In a separate assembly (let's call it DataAccess) reference the Common assembly and create the mappings for EntityFramework, using the DbContext and EntityTypeConfiguration<T> classes. This obviously means that you won't use any EDMX file but create your mappings with the fluent interface, which is anyway the best way to use EF.
At this point you have reusable and decoupled objects in an assembly and your data access logic and mappings in another assembly.
On top of this you can throw an IoC container to keep things even more decoupled but I think it's a bit off topic.

DDD - Restricting repository to create only certain entity

I have one important question about repository and entity. Should I restrict repository to create specific entity/aggregate root (via generic repositories like BaseRepository)?
At this moment, base repository have access to database factory object (not DbFactory but custom) to retrieve any POCO (not just related to aggregate root). So, technically, I can create any entity from any repository. Obviously, as a programmer I don't do it but it's definitely possible. So, is it necessary to restrict repository and allow it to create specific entity? Note that some entities have sub entities as well. So, if I restrict repository to create one entity (via BaseRepository) then how to create sub entities?
As #Jonas suggests in his answer, I'd create one repository per aggregate root. These should hide all persistence detail. This means taking domain entities as parameters and returning domain entities. Usually mapping from ORM entity to domain entity within the repository. As a side-effect, this also makes you think about what data you need, reducing some of the horrors you can encounter in DDD dealing with entities that have lazy-loaded properties.
I'd avoid the generic repository pattern, like you say in your original post, in DDD you want your code to document your design intention, you don't want to provide code that allows clients/callers to load any entity from your database. Also, most of your entities will most likely be built from many tables/resources, which doesn't apply well to the generic repository pattern.
I would consider it clear to have a Repository for each aggregate root in your Bounded Context.
It will make it obvious what an aggregate root is in your application opposed to what are (sub) entities. This way you are protecting yourself and others from harming how aggregates are accessed and used through repositories.

What is the best place for business logic in ASP.NET MVC when using repositories?

When implementing Repository for database in ASP.NET MVC project, is it correct to place business logic into it or may be better to place logic in controller class? Or use additional service and helper classes for manipulating data?
Ultimately there isn't a perfect place for your business logic besides its own layer (as part of the "Model" layer). Often you can get away with a different implementation, but there are trade offs in every case.
The trade off to creating another layer for the business logic is that you have to actually encapsulate your code. If you're too aggressive, you might also get some duplication between your entities and your domain model (if your DB's relational semantics already take care of your buiness logic).
View
The view is the most brittle part of your app, as it is the most likely part to change.
It is also very hard to get business logic correct in your view, due to having to support all the various view state transitions.
It is extremely well known these days that you just don't do this :)
Repository
The issue here is one of maintenance and purity of abstraction. Violating this can confuse people and make your app hard to maintain.
From the P of EAA article on the Repository pattern:
A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection
A repository is an abstraction that presents your data storage as a collection that holds domain objects.
No domain logic should reside in it. Instead, it should exist in your domain objects (by definition, as your business logic is your domain).
To do otherwise (to make your repository do double duty and also validate domain logic) would be a violation of SRP (Single Responsibility Principle), and would be a code smell.
You can have higher level domain objects that work with collections of domain objects to validate domain logic (such as dependencies within a collection of objects, size limits, etc). They will still use your repositories under the covers to do final storage/retrieval of domain objects, so they won't be doing double duty (so won't violate SRP).
Controller
The controller is also not a good place to put business logic. The controller's job is to mediate between the controller and the model.
The model is the domain, and the domain is your business logic.
Entities
You might consider putting domain data in entities.
But you must be careful when accessing navigation properties if the entities are attached, as you can trigger inadvertent DB queries or exceptions (depending on if your context is disposed or not). Detaching them is also a problem, as it destroys your object graph unless you explicitly reattach the objects to each other after detaching them from the context.
If you make separate domain model classes, you might consider treating entities as DTOs only.
Edit: IValidatableObject
I found out just now about a feature in Entity Framework 4.1 that you may want to check out: the IValidatableObject interface.
You can make your entities partial classes, and in the partial class, implement this interface. When you do, the Entity Framework will call Validate on save, and you can call Validate whenever it makes sense for you to do so.
This might help you avoid splitting your persistence model from your domain model in additional cases.
See this article: http://msdn.microsoft.com/en-us/data/gg193959
Side note: Views/View Models
In case you are thinking about it, I suggest you avoid the temptation to pass entities back to the view. It will break in a lot of cases (e.g. Javascript serialization to store view state), and cause unintentional DB queries in other cases. Pass back simple types instead (strings, ints, lists, hashsets, dictionaries, etc), or construct view model classes to pass to the view.
Add a Service Layer to pass models to Repository, where Service classes corresponding to the controller can be added. For example if you use a UserController and User Model, You can pass the User Model to UserService class.
Here the Service Layer can act as a bridge between the Repository and the controller so that the separation of Controller and Repository is well established.
Business logic should be there in your Domain model.
Please look into this answer.
ASP.NET MVC - Should business logic exist in controllers?
I agree with the above, controllers should not be responsible for business logic simply for returning the appropriate views. I use a service layer to provide business logic and view model creation so that a controller simply passes the model returned from a service to a view.
I also ensure my view models are simple DTOs, and the service simply knows how to populate the properties appropriately.
In my opinion it depends on the business logic. Is the logic based on validation of input and input rules, if so it may be best to be on the model. However, if it is business rules based on workflow then that may need to be in a controller, such as, user chooses option A then gets redirected to a different page/form than if option B was selected. If the business rules have to deal with data persistence then it may need to go in the repository (It would seem strange to put it there to me). There's a ton of discussion about this, but it comes down to you or your team's perspective about how maintainable and flexible the end product will be based on the implementation.

Repository; Mapping between POCOs / Linq-to-Sql entity classes

I'm making my first database program, with Sql Express. Currently I'm using Linq-to-Sql for data access, and my repository classes return "entity" type objects. Meaning; I extend the dbml entity classes to use as my business object classes. Now I want to make this more separated; and have POCO bussiness objects.
This is where I wonder about what different solutions may exist. It looks to me like I need to manually map property-by-property, each entity class into domain class, in the repositories. I have so far about 20 tables with total few hundred columns. Now.. I just want to verify if this is a common/typical approach that you still use? And if there are alternatives without introducing excessive complexity, what would that be?
Before creating your mappings manually, have a look at AutoMapper
AutoMapper is an object-object mapper.
Object-object mapping works by
transforming an input object of one
type into an output object of a
different type. What makes AutoMapper
interesting is that it provides some
interesting conventions to take the
dirty work out of figuring out how to
map type A to type B. As long as type
B follows AutoMapper's established
convention, almost zero configuration
is needed to map two types.
AutoMapper is a good tool to use to perform class-to-class conversions. However, I'm thinking of a DAL that combines Linq2Sql and AutoMapper, and I'm thinking why not just go with Fluent NHibernate? It's very easy to set up, works on just about any database including SqlExpress, and there is a Linq provider that integrates pretty seamlessly. All of this is free open-source code, and very commonly-used so there's ample documentation and support.
If you want to stay with Linq2Sql but have a more full-featured domain model, you could consider deriving your domain model from the DTOs. That would allow you to have the business logic in the domain, with the properties passed up to the DTO. However, understand that the Linq2SQL objects will not be able to be directly cast to domain objects; you'll need a constructor in the domain that takes a DTO and copies the info into the domain (requiring at least a one-way mapping of DTO to domain). However, the domain can be treated like a DTO (because a class is always its parent) so the reverse conversion isn't necessary; just hand the domain class to the repository where it would expect the DTO.

Categories

Resources