For the past few weeks, I’ve been learning and expanding my knowledge of the CQRS pattern. Under the guidance of Mr. Peter, I have been steadily progressing in my understanding of CQRS. This week, my focus was on implementing the final components of the pattern: the “Get by Id” and “Get List” functionalities for an entity.
First, I created the Get List Query Handler class. This class implements the IRequestHandler interface and is responsible for handling the query to retrieve a list of entities. It utilizes the IMapper and a specific service interface. Then, within the Handle method, I first check if the search name provided in the query is null and assign an empty string if necessary. This allows for more flexible search functionality. Next, I call a service to read the paged entity based on the search criteria and pagination details provided in the query.
To prepare the response, I use AutoMapper to map the retrieved list of entities to a list of the entity Dto objects. Additionally, I fetch the total count of entities that match the search criteria to assist with pagination. Finally, I return a PagedDto object containing the count, the mapped list, and the page and size information from the query.
Moving on to the Get Query By Id Handler class, which handles the query to retrieve a specific entity by its ID. Similar to the previous handler, it implements the IRequestHandler interface and relies on the IMapper and service interfaces. Inside the Handle method, I perform validation using the Get Query Validator. If any validation errors occur, I throw an InvalidOperationException with the corresponding error messages. Otherwise, I proceed to retrieve the entity using the service based on the supplied Id in the query. If an entity is found, I map it to the Dto using AutoMapper and return the result. However, if the entity is not found, I return null to indicate that no entity with the specified ID exists.
To ensure the correctness of my implementation, I have also included a couple of unit tests. These tests verify the success scenarios for both the Read By Id and Read List methods. They utilize a client to simulate HTTP requests and check the returned status codes and data.
In addition to the query handlers and tests, I have also expanded my knowledge by implementing another implementation of the service interface. This interface serves as the abstraction for fetching entities based on various criteria, and I made sure to create the methods in asynchronous form as advised by Mr Peter.
The added methods in the service interface provide the flexibility to retrieve entities by ID, search name, and pagination. For example, the ReadByIdAsync method accepts an ID as a parameter and fetches the corresponding entity asynchronously. It utilizes the underlying data access layer, to retrieve the entity. Similarly, the ReadPagedByAsync method takes parameters such as a search name, page number, and page size to perform a paged retrieval of entities based on the search criteria.
Overall, by implementing these methods in an asynchronous manner, I ensure that the retrieval operations can be performed efficiently and non-blocking. This enables better scalability and responsiveness in the application, especially when dealing with a large number of entities or concurrent requests. Moving forward, my next task involves delving into the UI aspect, where I will embark on learning about WPF, MVVM, and Prism.
