In our web application we have repositories with CRUD operations and a generic finder function, for instance userRepository.Get(u => u.Username == someString).
And UserRepository will return only User objects.
But what if I have a complex query which do the join between Table1, Table2 and Table3 and returns CustomObject which contains some properties from these 3 tables.
Should I put those queries in a Service layer?
Should repositories only contain basic CRUD and finder function and return basic entity object and nothing else? I ask because some people told me that no queries should be in Service layer...
I would probably create a type CustomObjectRepository which encapsulates the joining of tables and returns only CustomObjects. Exactly how to implement the generic finder function depends on what type of ORM you use (it will be trivial with EF, complicated but not at all impossible if you do manual mapping).
You can either have a Business logic View oriented Repository which stands one level on top of your current repository and name in according to that business logic.
Or you might apply hierarchical logic assigning this query to one of your existing repositories.
For example.
If you have 3 tables (Driver - Car- DriveSessions) and you need to display the User's First-Last Name, The car make,license plate and all the info of the last Drive session .
Using the 1st approach you would create a "Summaries" Repository.
Or you would add this in the "Driver" repository since all of these entities are oriented around a "Driver".
My opinion is adding a Repository in top of EF is an overkill . Some business models are so complex that it's kinda impossible to abstract everything on single repositories. That's why EF was designed for, with IQueryables. Encapsulating all your entities behind concrete repositories you lose most of the candy EF has to offer.
Opinions about using Repository pattern on top of EF
In my application i think not a single entity is non complex. Using a concrete per table repository would decrease performance and increase development time A LOT
Use the Query Object pattern. It's a much more SOLID approach. Furthermore, separating querying and CRUD, creates opportunities to use different, more appropriate infrastructure that might be better suited to custom querying. Also see: this
If you can, investigate what Vaughan Vernon calls a 'use cas optimal query' and beware of the smell that he calls 'repository masks aggregate mis-design'.
Related
I'm working on an ASP.NET MVC project in C# with an N-tier architecture.
A class (EmployeeRepo) in the database project has many functions.
Each function's natural result from the transaction is a dataset, but they are converted as per the need.
The return types are:
Dataset (with one or more tables)
DataTable
int
bool
Object (single employee)
List<Object> (list of employees)
Which is better among the two or is there a standard to follow:
Return the result as is without any conversion. The conversion should only happen at other layer and not in the database layer.
It is okay to convert the result in this layer before returning.
Return the result as is without any conversion. The conversion should only happen at other layer and not in > the database layer.
In my view, repository layer should only do one thing. And this thing is to query database without applying any business logic and return result. Why? There are some reasones such as:
it complies with Single Responsibility Principle of SOLID principles.
code becomes simpler
code becomes more reusable
class will have lesser size
easier to write tests
So all conversions are made in service layer.
In addition, it is not good idea to return Dataset (with one or more tables) or DataTable from repository. It is better to return IEnumerable<T>. I mean you should avoid to return IQueryable or DataTable from repository to avoid querying at service layer. There are many opinions about this. So you can choose what is better for you. Should Repositories return IQueryable? imho, repository should not return IQueryable as all query logic should be placed in one place and not scattered across services.
More over, I hihly recommend you to read this post about is it better to return the most specific or most general type from an action method?
Generally speaking, your repository layer will return entities and it is your service layer that will repackage those into a form appropriate for your application to consume.
Note that what constitutes an entity may differ from project to project. For instance, if you use Entity Framework then it uses ADO.NET under the hood but it packages the data into entity classes and returns those objects. You could, in theory, do the same but, if you do, I'd question why you're not already using EF or some other ORM. If you're going to use ADO.NET directly then you probably ought to be returning DataTables and/or DataSets to your service layer. You should certainly not do some of one and some of the other. Go all in with one or the other.
Part of the idea behind a separate repository layer is that multiple different service layers should be able to be laid on top and work seamlessly, so the repository layer should be pretty general, based on the data rather than the application. Conversions are going to require business logic and that belongs in the service layer.
I was debating whether to post this as an answer or vote the question as too opinion-based but I think that the roles of the various layers are well-enough accepted that it's not really opinion any more.
Ideally your repository layer returns data mapped to Domain entitites/Domain types.
So the repository implementation would convert from low level db/ado specific types to your DTOs / Domain Types.
This way, you keep your domain clean and don't let those db specific types trickle into your business domain.
I have a repository for an aggregate: Order and OrderRepository. Order has Products, Customer, etc. I'm using a micro ORM called dapper and .net core.
Here is my issue, when I need to save, I don't see how I can't break some DDD principle. I would like to have repositories for child entities of the aggregate i.e. ProductRepository, CustomerRepository and when I save the order it uses those repositories to save child entities but I understand that you can only have one repo per aggregate. I decided to just make a class called ProductPersistor, that would be internal to my infrastructure class library and called by the OrderRepository however then I can't use DI as it's configured .NET Core's DI framework in a different project. Furthermore it's still accessible by the classes in that class library. I can add all the insert update of all child entities into OrderRepository but that would be a gross SRP issue and still can't be injected using a DI container.
With regards to queries, the same issue stands although with dapper I can write a massive SQL JOIN and split it into different entities although that's not very efficient or flexible though.
I feel like I'm missing something. Can someone help?
Edit: As the comments below pointed out, Product and Customer can be their own Aggregate root. So let's replace those with Order and OrderLineItem.
Product and Customer seem like aggregates on their own, so they will need to have their own repositories ProductRepository and CustomerRepository. They should not be child entities of Order.
Your Order aggregate would be linked to Product and Customer, and the best way to do it between aggregates is to link on their unique identifiers.
A Repository is not equal or same as the underlying table - at least that is what DDD recommends. The Repository pattern sits between the aggregate data structure and the table/document structure, and represents the domain side of things. It's methods usually represent valid domain concepts: GetCompletedOrders(), GetTotalTaxAmount(), and so on.
An Application Service is supposed to handle the task of loading/persisting aggregates with the help of repositories, and that's the place where you would handle multiple repositories required for a process. This is where you can query other aggregates and get their identifiers, if necessary.
But I wouldn't recommend using multiple repositories as part of a single transaction in an Application Service. It violates the guideline that each business transaction should touch at most one aggregate. All other aggregates should be updated via Domain Events - they should become eventually consistent. Good for scaling and performance, this way. In your case, you may update Order aggregate, and bubble domain events to update Product and Customer, if necessary.
If you have complex queries and expect to run into performance problems (which I think you will as your system scales between Order, Product, and Customer), I would suggest you explore CQRS as an option. You don't have to implement it fully, but have readily available "Read" models in the background, with data already constructed in the format you want to consume. Background workers populate these "Read" models on a near real-time basis.
Please ask if this explanation does not cover all your questions or doubts.
I have some questions about the Aggregate Objects for Repositories.
I'm making a Rest Service with DDD/UoW/Repo and Service pattern. Our new cloud web-apps shall use this service. In order to do this, we also have to sync data from the old databases, which are still in production. We created a "SyncService" which read and writes to/from the cloud and down to earth.
In my Rest/DDD-design. And I don't want the business logic to run on these, so in the original test project I have a repository for every model and the endpoints just do some simple validation and push the data straight to the database using the repository.
Let's say I have these entities:
Customer
Order
OrderLine
Article
Database Relationsships:
A customer can have many orders.
An Order can only have one customer.
An Order can have many OrderLine's.
An OrderLine can have one Article.
Questions:
Are all of these aggregates except Article?
And which of these Entities would have a repository?
What would the repository look like?
Should I make endpoints for the "SyncService" to only talk to generic repositories for insertion?
Thanks in advance.
Are all of these aggregates except Article?
I believe it's impossible to answer this question without having access to the business logic and understanding how the whole Domain should look like. E.g. In some system, the Customercould be an aggregate and Order just an entity and in some other backward.
This decision should be made by an architect.
2,3,4. If you are using DDD you access your entities by your aggregates. I'd say the concept of using the repository pattern is optional. In some cases, you can just use pure DB context and e.g. if you are using for example Entity Framework Core you don't have to build extra repository layer over it as it is already a repository by itself. So the answer to these questions would be- it all depends.
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.
NOTE: I am not an expert, so if you feel this question stupid/lame please forgive and mind your business. :)
Ok, as all video tutorials tell, create a LinqToSqlClasses item (dbml) file. drag tables and we are done here.
But in my case (or probably in all real world scenarios), we need more from our Data Access Layer than just the auto generated classes, right?
For Example: In a simple accounting software: i have a Accounts Table and a AccountingTransactions Table,
Now to get any account's ledger we need to write a pretty Lengthy sql query, same goes for trial-balance, day book, and Single Vouchers et cetera.
What can we do in DAL to optimize these queries to have best performance.
I would recommend using Entity Framework over Linq to SQL.
But in both these cases, you have the power of Linq for such queries. Plus this gives you better designer support (intellisense, strong types, compile time checking)
EF or LinqToSQL becomes the lower level DAL and on top of this you would use the Repository pattern to call your Data Objects in a loosely coupled way. You could also add special methods for certain repositories to query data in a specific way if this needs to be encapsulated.
You should search SO for the repository pattern with Entity Framework or LinqToSql, you'll find a couple of implementations.
See this answer :
Advantage of creating a generic repository vs. specific repository for each object?