Non-Generic Reposiory pattern vs Generic Reposiory pattern

Repository Pattern Cover
Is a class to handle all possible DB operations for an Entity. Is used to separate DAL logic from BS logic of application, It acts as a mediator between them. Example: Repository for Employee entities, define all CRUD operations and other operations related to Employee. Provide a way to manage CRUD operations without directly interacting with DB, instead of writing DB queries directly in BS logic, we use IEmployeeRepository and EmployeeRepository class to handle, then EmployeeService in BL layer just depend on IEmployeeRepository, not actual DB. So BS logic does not need to know if data coming from DB, service or any source, just interacting with repository to handle task. Make code more cleaner and flexible, easy to write unit testing.

(one repository per Entity): Custom repository class for each entity, eg: UserRepository, EmployeeRepository.

(one repository for all Entity): Is an implementation of Repository pattern that allows us to create a single repository that can be used for multiple entities. Instead of writing sperate repositories for each entity, GR uses a single class with Generic type T parameter to handle CRUD. Simplifies DAL by reducing duplicate logic.

Code Example for Non-Generic Reposiory pattern

Controller (API Layer): Handles incoming HTTP requests and routes them to the appropriate service methods. It acts as a bridge between the client (frontend) and the BL. Example: GET `/api/employees/{id}` calls `EmployeeService.GetById(id)`.
Service (Business Logic Layer): Contains the core business logic and coordinates between the controller and the repository. Validates input, applies rules, and processes data before passing to/from the data layer.
Repository (Data Access Layer): Handles all interactions with the database. Encapsulates querying, inserting, updating, and deleting data. It allows services to work with data without knowing the source
Entity + DTO:
- Entity: Represents the real database model (e.g., `Employee`) used with EF Core.
- DTO (Data Transfer Object): A simplified version of Entity for transferring data between layers, especially to/from API.

Code Example for Generic Reposiory pattern

Controller (API Layer): This is the entry point of your application. It handles HTTP requests and responses. Calls methods from the Service Layer to execute business logic
Service (Business Logic Layer): Contains business logic and rules for handling application operations. Interacts with the Generic Repository to get or manipulate data.
Repository (Data Access Layer): Generic Repository handles all CRUD operations for any entity. You do not write a separate repository for each entity, ensure DRY principle.

Unit Of Work

Used to manage changes to multiple entities in a DB as a single Transaction (operation). If we want to implement transaction while using EF and RP, then UOF can be effective implementation of RP.

eg1: we are shopping and adding items to card, we don't want our order to be processed until we are done shopping and ready to checkout...
eg2: we have 2 account A (for debit card) and B (for credit card), money subtract from A and added to B, both must succeed together...
eg3: in application that interact with DB , we might be making multiple changes , such as update profile while sending notification. The UOW group these changes together...

Code Example for UOW

Controller (API Layer): Entry point handling HTTP requests/responses.
Service (Business Logic Layer): Uses UoW to coordinate multiple repository operations.
Repository (Data Access Layer+UOW): Repositories don’t call SaveChanges() directly. Instead, they only perform data operation. The Unit of Work will call SaveChanges() once.

Transaction (ACID)

  • Atomicity: all operation are completed successfully or non of them are...
  • Consistency: DB start and end in a valid state after transaction...
  • Isolation: transaction are like individual task that should not mixed...
  • Durability: once transaction complete successfully , its result are permanent...

Code Example for Transaction

We want to transfer money between two accounts. If debit from Account A or credit to Account B fails, the transaction must roll back.