I'm wondering about the utility of making a dal layer with EF.
Why not calling EF directly in business layer, considering EF DBContext is a unitOfWork and List DBSet are repositories ?
So why adding an extra DAL layer, wich is finally a facade..
The only advantage i see, is in case of we have to change the data access implementation, like replace EF by Hibernate or other. But honestly, i've never seen that happen.
Actually with a data mapper the necessity of developing a DAL is plain useless because it would contain 0 lines of code.
Everything on top of a data mapper isn't a data access layer but actual domain, because a data mapper implementation like an OR/M translates your objects into the underlying relational data and viceversa, and you work on top of them is to develop your domain and miss the pain of object-relational impedance.
The point of introducing the repository pattern on top of a data mapper is because you want to both be able to switch the underlying data store even to a non-relational one in the long run (also, switch from NoSQL to SQL, who knows!), and there's another definitive reason to introduce the repository layer in your software: because you want to be able to mock the data store with fakes in order to unit test your domain.
Finally, even when Entity Framework implements unit of work and other patterns, sometimes their implementation may not suit your own domain requirements and you need to wrap them to provide more concretion to your domain.
Related
I want to keep my controllers as clean as possible, so I want to put all the business logic inside the service layer, where I want to inject the DB context. It's worth clarifying that I am going to use EF Core.
Knowing that EF Core already implements the repository pattern and unit of work. I would directly inject the DB context into my services. I wouldn't want to create unnecessary abstractions such as a repository layer.
It is a common practice to inject DbContext into the service layer, it is however not instantaneously a GOOD practice on its own.
I want to keep my controllers as clean as possible, so I want to put all the business logic inside the service layer
That statement can be contradictory, you want everything in one place and you want to keep it clean as possible... This is the major driving argument behind implementing your own repository.
Repository and Unit of Work
A key goal of the Repository Pattern is to try and encapsulate data transformation and query logic so that it can be reused and separated from the database design itself
Unit Of Work is concerned with tracking changes and coordinating how and when those changes are committed to the database, perhaps across multiple repositories.
EF DbContext manages a Unit Of Work implementation over a Repository of Business Domain Entities that are mapped to Database Schema Tables. EF therefore represents both UOW and Repo.
When Is EF A good Repo?
Just because EF is A Repo, does not mean it is THE Repo for your solution, EF can be the perfect repo for the business domain logic has direct access to it, disconnected service architectures can however get in the way of this, unless your entire business logic is encapsulated in the service layer, so every button click and decision point in your client/UI is mapped back to the API, then there some of the business logic spills over into the client side, so an EF based service layer requires a lot of plumbing if you were to expose all of the functionality that the client needs in a meaningful way.
If you end up mapping all or the majority of EF model classes into DTOs or have an entirely different business model that you want to expose to clients, then to do all of this in your API Controller classes can easily become a huge management and maintenance issue, with APIs Controllers you really need to separate the routing and De/Serialization of requests and responses from the actual logic, using another Repo to encapsulate the logic implementation from the transport (the controllers) is a good thing, this usually means that you would NOT inject the DbContext, unless it was simply to pass through to the Repo for that controller.
If the EF Model is not being exposed by the controller, then it is better to avoid injecting the DbContext into the controller, as it will encourage you to do too much in the controller itself.
Lets consider when it IS a good practice to inject the DbContext into the service layer:
In a tiered solution with a Service Layer, if the EF Model represents the main DTOs that will be transferred between the Service and the Client, then EF is a good choice to use in the controllers directly. In fact if that is your goal, then you should consider OData as a service framework as it does this and provides an additional layer of abstraction (the OData Model) that is initially mapped to the EF model but you can easily extend elements to implement custom business logic or structures with theadded benefit of exposing a convention based standard interface for querying data from the clients.
OData basically maps HTTP queries to deferred EF queries, which are in turn mapped to SQL queries (or whatever your chosen backend is). If you use the Simple or Connected OData Client frameworks then Client-side linq statements can be passed through (albeit indirectly) to the database for execution.
When your EF Model represents the bulk of the DTOs exposed from the service and consumed by the clients, then it is a standard practise to inject the DbContext into the Controller definitions, OData is an Implementation that does this with minimal effort and provides a client-side implementation to manage UOW on the client as well!
Why do I need another abstraction layer
As mentioned above, due to the disconnected nature of things, the service layer almost always ends up forming its own abstraction layer, whether you choose to identify or implement them or not, the service layer imposes security and structure constraints on the calls to our business logic. Sometimes we transform data on the service side for efficency or reduction in bandwith, other times to deliberately hide or withold confidential or process critical data, or prevent the client from updating certain fields.
There is also the question of protocols, most modern APIs even add Content Negotiation such that the service can be consumed by different formats as specified by the client. Your controller code will get extremely heavy and dare I say dirty whne you start to tweak some of these factors.
You can gain a great deal of flexibility and interoperability from creating your own repo to manage these interactions, to separate transport and bindings from your business logic.
I wouldn't want to create unnecessary abstractions such as a repository layer.
In a small project or with a very small team it may seem unnecessary, but many of the benefits to creating your own repo will be realized later, either when on-boarding new developers, extending your project to more or new types of clients or perhaps importantly, when the underlying frameworks or operating systems change and you need to adapt to them.
Another abstraction layer shouldn't mean that you are introducing another performance bottleneck, in most cases there are ways to abstract the business logic in a way that either improves the throughput or is effectively pass through. Any performance loss, if observed should either be fixed or it should be easily justified in the net gains to the user or SDLC.
With service based architecture it is normal to see these abstractions:
Database
Data Model
ORM
Business Logic
API Transport (Server)
(HTTP)
API Transport (Client)
ViewModel
View
If you utilise SQL Server, EF and OData, then the only elements you need to explicitly code yourself are:
Data Model
Business Logic
(HTTP)
ViewModel
View
In the end, it is not a question of should the DbContext be injected into the controller, its more of a question about why? Its the Business Logic side of things that matters, this usually requires your DbContext, if you choose to merge your business logic with the API controllers, then you are still managing the business logic, its just harder to identify the boundaries between what is transport related and what is actual business logic.
If the business logic needs to be a separately defined repository or can be an extension of the DbContext is up to you, It will depend greatly as reasoned above on whether you expose the EF Data Model objects through to the client at all, or if all interactions need to be transformed to and from DTO structures. If its ALL DTOs and Zero EF model being exposed, then this falls 100% into the realm of a Repo. Your controllers can be the repo implementation, but everything said before this suggests that is not the best idea for the long term stability of your development team or the solution itself.
As an example, I often write my business logic as extension methods to the EF Model. I use the EF as the repo in this case, this allows many other server side processes to access the business logic without having to go through the HTTP activation pipeline when it makes sense to do so.
T4 templates are used to generate the service layer including OData Controllers from the EF model and the extension methods that are specifically decorated with attributes to identify those moethds that should be available to external clients.
In this implementation, the DbContext is injected to the controllers, because that is the entry point to the business logic!
The client-side projects use the OData Connected Service to generate clien-side proxies providing a strongly typed and linq enabled context that is similar to the DbContext but with the business logic carefully constrained within it.
Background
At the company I work for I have been ordered to update an old MVC app and implement a repository pattern for a SQL database. I have created the context of the database using Entity Framework Database-First and got 23 entities.
The first question
Do I need to create a repository for each entity or implement a generic repository for the context? I'm asking this because I have found following while searching internet:
One repository per domain
You should think of a repository as a collection of domain objects in memory. If you’re building an application called Vega, you shouldn’t have a repository like the following:
public class VegaRepository {}
Instead, you should have a separate repository per domain class, like OrderRepository, ShippingRepository and ProductRepository.
Source: Programming with Mosh: 4 Common Mistakes with the Repository Pattern
The second question
Does a generic repository work for Entity Framework Database-First? This is because I have found following while searching internet:
Entity framework
Do note that the repository pattern is only useful if you have POCOs which are mapped using code first. Otherwise you’ll just break the abstraction with the entities instead (= the repository pattern isn’t very useful then). You can follow this article if you want to get a foundation generated for you.
Source: CodeProject: Repository pattern, done right
To begin with, if you are using full ORM like Entity Framework or NHibernate, you should avoid implementing additional layer of Repository and Unit Of Work.
This is because; the ORM itself exposes both Generic Repository and Unit Of Work.
In case of EF, your DbContext is Unit Of Work and DbSet is Generic Repository. In case of NHibernate, it is ISession itself.
Building new wrapper of Generic Repository over same existing one is repeat work. Why reinvent the wheel?
But, some argue that using ORM directly in calling code has following issues:
It makes code little more complicated due to lack of separation of concerns.
Data access code is merged in business logic. As a result, redundant complex query logic spread at multiple places; hard to manage.
As many ORM objects are used in-line in calling code, it is very hard to unit test the code.
As ORM only exposes Generic Repository, it causes many issues mentioned below.
Apart from all above, one other issue generally discussed is "What if we decide to change ORM in future". This should not be key point while taking decision because:
You rarely change ORM, mostly NEVER – YAGNI.
If you change ORM, you have to do huge changes anyway. You may minimize efforts by encapsulating complete data access code (NOT just ORM) inside something. We will discuss that something below.
Considering four issues mentioned above, it may be necessary to create Repositories even though you are using full ORM - This is per case decision though.
Even in that case, Generic Repository must be avoided. It is considered an anti-pattern.
Why generic repository is anti-pattern?
A repository is a part of the domain being modeled, and that domain is not generic.
Not every entity can be deleted.
Not every entity can be added
Not every entity has a repository.
Queries vary wildly; the repository API becomes as unique as the entity itself.
For GetById(), identifier types may be different.
Updating specific fields (DML) not possible.
Generic query mechanism is the responsibility of an ORM.
Most of the ORMs expose an implementation that closely resemble with Generic Repository.
Repositories should be implementing the SPECIFIC queries for entities by using the generic query mechanism exposed by ORM.
Working with composite keys is not possible.
It leaks DAL logic in Services anyway.
Predicate criteria if you accept as parameter needs to be provided from Service layer. If this is ORM specific class, it leaks ORM into Services.
I suggest you read these (1, 2, 3, 4, 5) articles explaining why generic repository is an anti-pattern. This other answer discusses about Repository Pattern in general.
So, I will suggest:
Do NOT use repository at all, directly use ORM in your calling code.
If you have to use repository, then do not try to implement everything with Generic Repository.
Instead, optionally create very simple and small Generic Repository as abstract base class. OR you can use Generic Repository exposed by your ORM as base repository if ORM allows it.
Implement Concrete Repositories as per your need and derive all them from Generic Repository. Expose concrete repositories to calling code.
This way you get all the good of generic repository still bypassing its drawbacks.
Even though very rare, this also helps switching ORM in future as ORM code is cleanly abstracted in DAL/Repositories. Please understand that switching ORM is not a primary objective of Data Access Layer or Repository.
In any case, do not expose Generic Repository to calling code.
Also, do not return IQueryable from concrete repositories. This violates basic purpose of existence of Repositories - To abstract data access. With exposing IQueryable outside the repository, many data access decisions leak into calling code and Repository lose the control over it.
do I need to create a repository for each entity or implement a generic repository for the context
As suggested above, creating repository for each entity is better approach. Note that, Repository should ideally return Domain Model instead of Entity. But this is different topic for discussion.
does a generic repository works for EF Database First?
As suggested above, EF itself exposes Generic Repository. Building one more layer on it is useless. Your image is saying the same thing.
I am trying to create a system that allows you to switch multiple data sources, e.g. switching from Entity Framework to Dapper. I am trying to find the best approach to do this.
At the moment I have different projects for different data layers, e.g. Data.EF for Entity Framework, Data.Dapper for Dapper. I have used a database approach but when it creates the models the information generated is coupled together and not easy to refactor, e.g. separation of models.
I have a project called models, this holds domain and view models, and I was thinking of creating Data.Core and follow the repository pattern. But then, doing this will add an extra layer so I would have Presentation / Business / Repository / Data.
I would like to know the best structure for this approach. Should I also do a code-first approach to create my database? This helps separate concerns and improve abstraction. This is quite a big application so getting the structure right is essential.
I'd suggest factoring your data interfaces either to the model through repository interfaces for your entities or to an infrastructure project. (I think the latter was your rationale behind creating a Data.Core project.)
Each data source will then implement the very same set of interfaces, and you can easily switch between them, even dynamically using dependency injection.
For instance, using repositories:
Model
\_ Entities
Entity
\_ Repositories
IEntityRepository
Data.EF
EntityRepository : Model.IEntityRepository
Data.Dapper
EntityRepository : Model.IEntityRepository
Then in your business you won't need to even reference Data.EF or Data.Dapper: you can work with IEntityRepository and have that reference injected dynamically.
I think you approach is correct. I'd say Presentation / business / repository / data is pretty standard these days.
I'd say the code first approach using POCOs is the preferred option today in the industry. I would advise to start creating a project containing your POCO data structures with any logic in it and take it from there. The advantage of this is that your objects model the domain more naturally. If you start with a db centric approach the problem is that, if you are not careful, you may end with objects more akin to SQL relational databases than to the real model. This was painfully evident in the first versions of .net where it was encouraged to use Datasets tighly coupled with the db and that often caused problems to work with in the business layer.
If needed you can do any complex mapping between the business objects and the db objects in the repository layer. You can use a proxy and/or a unit of work if you need to.
I would suggest you create your domain objects, use the code-first approach and also apply the repository pattern
Yes the repository pattern does bring in an extra layer. Have a look at this post for more detail information Difference between Repository and Service Layer?
RE: code-first approach to create my database
It doesn't matter how big your application is, it is a question of what else you intend to use the database for. If this database is simply a repository for this application then using code-first is fine as you are simply storing your code objects. However if you are using this database as an integration point between applications then you may wish to design the database seperately to the application models.
I use Entity Framework as ORM in my .net MVC project. I've implemented the Repository-Pattern (generic) to get/save/update/remove DAOs (Data Access Objects). I also have Business Objects which contain all the business logic. I have - for example - a DAO called Student and a BO (Business Object) called Student as well. The BO contains the logic, the DAO just the data stored in the DB.
Now I am wondering if the Student-Repository should return the Business-Object instead of the DAO?
I could achieve that using Automapper by converting the DAO to a Business Object before returning it from the Repository.Get(). Same with all the other methods. But is this a good practice?
Update
I have a Data Access Layer project and a project for the Business Logic. Entity Framework creates its entities in partial classes (into the Data Access Project) so I could actually extend the entities with other partial classes but the problem is that I reference the Data Access Project in my Business project and I don't have access to the logic code within the Data Access project. So I have to put the logic inside the Business project but as it is not possible to create partial classes over two projects I have to go another way... or do you have a good idea how to structure and solve the problem in a better way?
IMHO there are several goals (some competing):
Make business logic testable in isolation
Design domain objects to match your domain
Decouple data access from everything else
Keep it simple
Can you test your business logic without a database? Probably yes, whether the classes are EF POCO entities or mapped from DAOs.
Do your domain objects match your domain? Are their names well-chosen? Are they always in a valid state? (This can be difficult with a bunch of public read/write properties.) Domain-driven design considerations apply here. (I'm no expert in that.)
Could you swap out EF for Dapper, SQL Server for MongoDB, or current data access for a web service call without changing anything outside the data access layer - with confidence? My suspicion is no. Generic repositories tend to leak IQueryable into other layers. Not everything supports querying, and provider implementations vary. Unit tests typically use LINQ to Objects, which does not behave the same as LINQ to Entities. Also, if you want to extract a web service contract, you would have to look through all classes to find all the queries. See IQueryable is Tight Coupling.
Finally, do you need all of this? If your application's purpose is CRUD data access with no business logic above simple validation, maybe not. These considerations definitely apply to a complex application or site.
Yes, that's totally good practice. Usually you have repository interfaces defined in domain assembly. These interfaces are used by domain services, and implemented in persistence assembly. Entity Framework allows you to map business entities fluently, without polluting them with attributes or forcing them to inherit from some specific base class (POCO entities). That makes your domain model Persistence Ignorant.
I've been reading about POCO (Plain Old CLR Object) for a while but still can't find the real added value of using it instead of using the auto generated partial classes of the entity framework?
One more thing is it best to use my entity framework directly from the presentation layer or creating a BLL will be better?
The main benefit of a POCO is that you can pass it to a class, library or assembly that doesn't need to know anything about Entity Framework to do its job.
Remember the Single Responsibility Principle - your DAL should know about EF, but your Domain should not, and neither should your presentation layer, because EF deals with data access and those layers do not. Passing EF generated class objects up to those layers generally means you need to make those layers aware of EF, breaking the SRP and making it harder to unit test those layers in isolation.
In response to Ali's further query in the comments below, here is an expanded explanation.
In more complex applications, you will want to split the logic up into separate concerns - data access, business logic, presentation (and perhaps a lot more).
As entity framework deals with data access, it resides in the data access layer - here, you will see little difference between POCOs and EF generated classes. This is fine, because this layer already knows about Entity Framework.
However, you may want to pass data up to the business logic layer - if you do this with EF generated classes, then your business logic layer must also know about Entity Framework because the EF classes rely on a lot of things EF provides specially. What this does is remove the isolation that your business logic layer should have - you need this isolation so you can unit test it correctly by injecting known data into the class from a fake data access layer, which is incredibly hard to do if you let the business logic layer know about EF.
With unit testing, you should be testing the layers functionality, not the functionality of third party libraries - but with EF you end up testing a lot of EF's functionality, or your own functionality which relies very heavily on that of EF's. This isn't good, and it can mask errors or issues.
Removing the business logics dependency on EF generated classes also allows you to move the layer to as remote a location as you like from the data access layer - you can even stick it behind a web service and it would be completely happy. But you can only do this with POCOs, you cannot do this with EF generated classes.
POCO's really come into their own in large, complex multi layered applications - if you aren't layering your app, then you won't see a whole load of benefits imho.
All of this is my opinion, and I'm just a coder with experience - I'm not a coding rockstar, so some other commenters may like to further expand my answers...
The real benefits with POCO is that you can use code first and EF Migrations. If you are not going to use code first you can use the designer generated classes.
If you have a large application you should create a separate BLL, but if your application is very small you can probably go directly with the EF classes in the presentation layer.
Using POCO classes in an ORM allows you to create tests for that code in an easier manner. It also allows you to have a layer of abstraction between your model objects (the POCO classes) and the data access code so if you need to you can swap the data access code (EF for NHibernate, for instance).
I've worked with the POCO model in the past and I can tell you that it's useful for big enterprise projects and large teams of developers where changes to the model happen often and where the monolithic file model used by default by EF does not scale well. The benefits on small projects or in rapid application development are hard to see.
TLDR version: If you're asking yourself what the benefits of POCO and code first are, you probably won't gain anything from using them.