I have developed an application with following layers:
Data access layer based on fluent nHibernate
Business rules
activity layer(more abstract than business rules and use some
business rules)
service layer based on WCF that sends some DTOs to the outside world
and recieves DTOs.
so when some DTO came back, I can map the DTO to business objects in the service layer and made my application to work with business objects. in that case when some function in lower layers executes it does not know any thing about the old object, so it become hard to handle and verify state changing and also there is class explosion for DTO adapters.
on the other hand if dto is mapped to business object on the higher layers, when it came down, the lower layers did not know anything about the service which is called, so they can not unserstand how this dto must change the business objects(1 DTO might be used by different services in different ways)
so the question is what is the real solution??
From your specs, I'm kind of assuming you are aiming for a DDD based implementation
First, some assumptions to help map this to more common terminology: I assume your "Business Rules" layer is just used by your activity layer, and thus can be considered as part of the domain layer.
You mention business objects. I assume then that you have a domain layer. This might be your "activity layer". This should be the layer that knows how to update objects and return them to the service layer.
The service layer (or "application layer" in DDD terms) should be mapping the DTOs, and invoking domain services. MS has a decent diagram here. But basically the workflow should be:
Send DTO to service layer
Service layer invokes DTO adapters to create domain objects/entities out of DTOs.
Service layer invokes domain services to perform business logic (invokes rules)
Domain services update domain objects as a result of business rules
Persistance layer is invoked by domain services as needed
Domain services return updated domain objects to service layer
Service layer maps domain objects back to DTO and returns them
There are of course many variations on this theme, but this should be your starting point.
Related
I have .net core api project with following folders:
Models contains the database table classes and dbcontext
Services contain logic to send email, and business logic (example calculate student grade based on marks)
Controller contains the controllers with respective actions (api endpoints). The dbcontext is injected into the controller and the endpoints contain the LINQ queries (example: _ctx.Students.Where.....)
I want to organize this into layered architecture.
UI layer will contain the api project (controllers) and reference the business layer dll.
Business layer will contain the send email logic, and business logic (grading based on marks). I think this must reference the data layer to be able to fetch data.
Data layer will contain the table classes and db context.
Where do I place my entity framework queries which were previously in the controller action method?
I usually recommend people to use the repository pattern to structure Asp.net application in a monolithic fashion. At a high level, there are usually three-layer
Repository/Data Layer
Service/Business layer
Controller/API (Web Project)
In Repository Layer, we define all our models and database call(Your Entity framework will be here).
In the Service Layer, We perform all the business logic.
And in the web project, we define all the API endpoints and other client-side interaction services.
The followings are some of the articles related to the Repository pattern:
https://www.linkedin.com/pulse/repository-pattern-c-pawan-verma/
https://medium.com/net-core/repository-pattern-implementation-in-asp-net-core-21e01c6664d7
https://codewithmukesh.com/blog/repository-pattern-in-aspnet-core/
Some articles, here use the same project to define all the layers but you can simply separate all layers into a separate project (class library).
I usually layer my application like this:
APIs - EndPoints
Application Layer - All glueing code, mapping, orchestra code, utilities, and other application-level code comes here
Domain Layer - Purely contains domains, sub-domains, validations, interfaces for repositories and unit of work, and commands.
Data Layer - This layer contains the implementation of all the repositories and unit of work interfaces. And this is the layer where I keep all my queries and database-specific code.
Is it not bad practice to pass DTO object to service layer?
For now my service layer method look like this:
public save(MyEntity entity);
Mapping values from DTO to business entity (MyEntity) is done on presentation layer
But I want to change method signature to this:
public save(MyEntityDTO dto, String author);
And after it mapping from DTO to business entity will occur on service layer.
EDIT: I want it because I need opened hibernate session when mapping from DTO to business object, so all changes on entity will be automatically flushed.
Is it not bad practice to pass DTO object to service layer?
Not only you could pass DTO objects to Service Layer, but you should pass DTO objects instead of Business Entities to Service Layer.
Your service should receive DTOs, map them to business entities and send them to the repository. It should also retrieve business entities from the repository, map them to DTOs and return the DTOs as reponses. So your business entities never get out from the business layer, only the DTOs do.
See the full answer to a similar question here.
It's debatable. (As evidenced in comments to the accepted answer)
On the one hand, DTOs are belong to the layer of the application that deals with Data Transfer, which is your presentation layer apparently.
On the other hand, your domain object (business entity), which is properly dealt with in the service layer, probably has properties in it - like, say an Id, a LastUpdated or such that are not passed into the save method. So what do you pass in? Well, you pass in just the properties you need. And it just so happens, that the request MyEntityDTO for save() will happen to encapsulate all and only those properties!...
So you now have the unfortunate choice between:
Passing in the business object from the presentation layer
(Breaks the layering model too, and forces you to ignore properties
like Id and LastUpdated, which are not in the "request")
Breaking up the DTO into properties and passing them in:
service.save(Dto.Property_One, Dto.Property_Two)
which you then have to put back together in the save() method.
Creating some new object to encapsulate Property_One, Property_Two etc
Accepting that the DTO is for transferring between layers too
None of these is ideal imo, which is why I think #4 is okay. Probably the most correct is #2 - but again.. not ideal.
Sometimes naming my ease the pain: "MyEntityRequest" instead of "DTO"
It's ok, all standard 3 layer architectures do that. Dataaccess gets the data, business maps and manipulates it, presentation presents it. It is not ok - but, as said no crime - to pass dataaccess models to presentation - to this point u should pass business models. Btw. "DTO" can mean anything, business layer models can be DTO's, data access model can be DTO's. DTO's are usually POCO's in C#. Usually you have your dataaccess models, representing your database entities and your domain models wich pass the data around your application. The domain models are usually DTO's (or call it POCO). That means, in Microsoft speech, they are completly serializable, so you can pass them to any microsoft .net component. You can serialize them also to xml, json and so on ...
Just a quick question about my Domain Layer/ Domain Service... Should I allow this layer to have read only access to the database? i.e. hook up a IReadOnlySession and only allow the Repository Layer to have access to CRUD i.e. Persistence? Or should the Repository Layer do both the ReadOnly and CRUD with the service layer making a call to the Repository layer?
One thing I find rather strange is why most of the time the Service Layer is only making a direct call to the Repo, hence the question - move out ReadOnly to the Domain Service Layer.
EDIT:
I have decided to have 3 layers in my app (for anyone who is interested in what I have done), the first layer is the WebUI (I will have 3 in total, business requiement), below this is the Domain Service i.e. All business rules, validation, checking if user can do action x, user is valid user, calling the repo for the data. The final layer is the Repository Layer i.e. the layer that talks to the database iteself, I am using LinqToSql, all my CRUD and ReadOnly logic resides here. As a side note I created another project called Model, this is the actual LinqToSql model entities i.e. Product, Item, Shop, Customer etc. This very project is referenced by the UI, Domain Service and Repo, saving me from writing DTO, and from unecessary complexity hopefully.
In your application, only one 'layer' should talk to the database.
In the Repository pattern, it's the Repository.
It doesn't matter if it's CRUD or ReadOnly, it should go through the repository to the database.
I see the discussion as what are the responsibilities of these layers. The repository is clearly to provide an abstraction over the db. Done correctly and the users of the repository cannot tell if you are using SQL server, mysql or files for persistence. This layer must have all the necessary crud operations.
The service layer is another abstraction. It may depend upon the repository for persistence. There is usually a bit more business logic. Maybe cross repository concerns or another stream of data (gps for instance).
Some apps don't need a service layer. Don't add it until you need it. If you do have the need for the service layer, letting it be a thin rapper around the repo exposing read/write allows your models to only have one direct dependency.
Scenario
Data Access Layer
EF's generated .edmx and classes
Used only to access the SQL Database and pass the data forward to the business layer
Business Layer
Business entities : contain all validation logic, marked with the [DataContract] attribute so that they can be passed as parameters to my web service
Problem
I want to use the repository pattern with this approach. The repository would contain all CRUD operations to be performed on the database, accepting and returning business layer entities. This means that the repository will reside in the business layer, because only the business layer can reference the data layer, not the other way round. I'm also planning to use the data layer assembly in other projects, that's why I would like to have the repository in the data layer, not the business layer (which is particular for this project).
What do you recommend? Should I keep the repository in the business layer and write one for each different business layer? Or should I keep the repository inside the data layer, not accepting or returning business entities.
Or, as an alternative, can anyone recommend a different approach, that would yield a more logical, scalable architecture?
Thanks for reading, waiting for answers
A repository is an abstraction over the data layer - to afford persistence ignorance to your application. It should only deal with data access and nothing more. It should not have any business logic.
The repository can and should accept and return DTOs (Data Transfer Objects) - these are simple objects that do not have behavior of their own and are used to transfer data between layers.
I would put it between the DAL and the BLL and only use it for data access from the BLL.
I like the accepted answer. Ideally, having a completely layer dedicated to the Repositories sounds right.
But I think, in a traditional 3-tier only application (e.g. "Data->Business->UI"), I would stick the Repositories in the Data layer. The reason I would put them in the Data Layer, is because they deal strictly with data access. The reason I would NOT put them in the Business Layer, is because they should NOT have any business logic to them.
I think repository interface should be in business layer, but implementation of this interface should be in data layer. Interface enable unit testing, but repository implementation is not responsibility of business layer.
I have an application with three layers (Presentation, Business Logic, and Data Access). In the data access layer, I have an object called Unit, and I have another object called Unit in the business layer.
When Insert() is called on the Unit object in the business layer, it calls the Insert() method on the corresponding object in the data access layer, and passes itself as the parameter. The problem I have is that the data access layer does not reference the business layer, and allowing it to do so would cause circular dependencies.
Is my approach flawed? If so, what would be a good solution to my problem?
You're right when you state that the way you're doing it would require a bidirectional dependency between layers, and that's almost always a bad thing. The reason for this dependency is that your business logic layer takes on some of the responsibility of the persistence layer (by implementing Insert() in the business logic layer).
It seems like you're mixing two incompatible concepts here.
First, you state that you have three layers in your code: presentation, business, and data access. The problem with this statement is that you also claim to be using an active record like pattern (unit.Insert()). If you truly have a distinct domain (business) layer and persistence (data access) layer, then the domain objects would not know how to Insert().
Take a look at the repository pattern. This pattern is better suited for establishing a distinct persistence layer. If you use this pattern, you can define an "Entity" in the persistence layer, and map your Unit object in the domain layer to the Unit object in the persistence layer. AutoMapper should save you from the pain of manually mapping the domain model to the entity.