This is part 13 of Blazor Tutorial. In this video we'll learn, what is repository pattern? Benefits
of it and finally, an example that uses repository pattern to store and retrieve data from a SQL
server database. What is a repository pattern? Well, repository pattern is an abstraction of
the data access layer, it hides the details of how exactly the data is saved or retrieved from
the underlying data source. The details of how the data is stored and retrieved is in the respective
repository. For example, you may have a repository that stores and retrieves data from an in-memory
collection, you may have another repository that stores and retrieves data from a database like
SQL server, yet another repository that stores and retrieves data from an XML file. Let's understand
what this all means with an example. We want the Blazor application that we are building as part of
this course to be able to perform CRUD operations, that is Create, Read, Update and Delete against
employee objects. Notice this interface right here, IEmployeeRepository contains methods
that perform the respective CRUD operations. Consider this first method GetEmploys(), this
method returns us the list of all employees, that is IEnumerable objects. We made this
method return a task, because we want this method to be an asynchronous method, and the same is
true for the rest of the methods here. This method Get'Employee() returns employee by ID, we pass it
the ID of the employee whose details we want as a parameter and this method returns that respective
employee. AddEmployee() adds a new employee, Update updates and delete deletes. This interface
is the abstraction and will be programming against this interface. This means just by looking at this
interface we cannot really tell where will the employee objects be retrieved from or
stored. Will they be retrieved from an underlying database, an XML file or an in-memory collection?
These are the implementation details and they will be present in the respective repository.
So, the point that I'm trying to make is, the interface in the repository pattern specifies
what operations i.e methods are supported by the repository. We only specify the data required for
each of the operations, that is the parameters that need to be passed to the method and the data
the method returns. As you can see, the repository interface contains what it can do but not how it
does what it can do. The implementation details are in the respective repository class that
implements this repository interface. If we take a look at the project we've been working with,
notice in the "Models" folder of our API project I've already included this repository interface
"IEmployeeRepository". Our obvious next step is to provide implementation for this repository.
We want to store and retrieve employees from a SQL Server database and this specific implementation
of the repository is going to do exactly that. Notice, our class EmployeeRepository implements
the interface IEmployeeRepository and the first thing that we're gonna do here is
inject our application specific DB context class "AppDbContext" class into this employee repository
using the constructor. We implemented this class in our previous video and it knows how to work
with an underlying SQL server database and you can find this class in the same "Models" folder.
So we are injecting this application specific DB context class into our employee repository
using dependency injection and if you're new to dependency injection, we discussed it in detail
in part 19 of our asp.net core tutorial for beginners course. We have the implementation
for GetEmployees() method. Notice this method doesn't take any parameters and returns us an
IEnumerable objects that is the list of all employees. Getting the list of all employees
is straightforward. On the injected AppDbContext instance we have the "Employees" property that
returns us the list of all employees from the SQL server database table - "Employees". Similarly,
we have to provide implementation for the rest of the methods, that is get, add,
update and delete employee. I have already added the class file "EmployeeRepository.cs"
to the "Models" folder. We want this class to provide the implementation for the repository
interface "IEmployeeRepository". Next, we need an instance of our application dbcontext class
to be injected into this employee repository, so let's include a constructor first. Our application
dbcontext class is "AppDbContext". Let's call the parameter "appDbContext" and generate the required
private field by pressing control period. First, let's provide the implementation for
AddEmployee() method. We want this to be an async method. To add a new employee, on the injected
"AppDbContext" instance we have "Employees" property and on that we have AddAsync()
method and to this method we pass the incoming employee object. Since this is an async method
let's await its execution and store the result in a variable called "result". Next, we need to call
SaveChanges() on the AppDbContext instance, again we have SaveChangesAsync() so let's use that and
await this methods execution and finally we want to return the added employee object so on the
result we have "Entity" property which is going to return us the added employee object. Let's close
this solution Explorer to get a bit more room. Let's make this DeleteEmployee() method also
async and here is the implementation. We have a red squiggly on the FirstOrDefaultAsync(),
that's because this method is present in "Microsoft.EntityFrameworkCore" namespace,
so let's bring that in and the implementation is straightforward. First, we are using the incoming
"employeeId" to retrieve that respective employee from the database using "AppDbContext". If we
have found the employee we are removing that employee and then calling "SaveChangesAsync()"
method on the "AppDbContext" instance. Next, GetEmployee(). First, let's make this async
and here is the implementation, just one line of code here, use this incoming "employeeId" to
retrieve the respective employee. Next, we have GetEmployees(). Again, let's make this async
first. This method doesn't take any parameters and returns the list of all employees. Finally,
UpdateEmployee(). To update an employee, we first retrieve the existing employee object from the
database using this incoming employee object "employeeId". If we have found the employee, we
then override all the properties of the employee object we have retrieved from the database using
this incoming employee object properties and then call SaveChanges() and return the updated employee
object. Just like EmployeeRepository, we need another repository to manage employee departments.
We are not going to create, update or delete departments, we just need two methods here. A
method that returns us the list of all departments and a method that returns department by ID. Here's
the implementation. DepartmentRepository class implements the interface IDepartmentRepository
and in to this repository class we are injecting our application dbcontext class using the
constructor and then we have the method that returns us the list of all departments from the
SQL server database and this method returns the department by ID. To the models folder of our API
project I've already added IDepartmentRepository interface and the implementation. Finally,
we need to tie the repository interface and the implementation classes together. We do this in
the ConfigureServices() method of the Startup class. With these two lines of code here asp.net
core provides an instance of DepartmentRepository class when an instance of IDepartmentRepository
is requested. Similarly an instance of EmployeeRepository class is provided when an
instance of IEmployeeRepository is requested. At the moment, we are using AddScoped() method to tie
the repository interfaces and the implementation classes together. In addition to AddScoped(),
we also have AddTransient() and AddSingleton() methods. We discussed the difference between
these methods in detail in Part 44 of our asp.net core tutorial course. I have already included
the code that we've seen just on the slide in ConfigureServices() method of the Startup class
of our API project. With this code in place throughout our entire application wherever
IEmployeeRepository is injected an instance of EmployeeRepository class will be provided. Later,
if we want to swap this EmployeeRepository implementation with a new implementation,
all we need to change is this one line of code, instead of using EmployeeRepository class here,
we use our new implementation class. What are the benefits of a repository pattern? Well,
there are many. The code is cleaner, easier to reuse and maintain. It enables us to create
loosely coupled systems, for example, if we want our application to work with Oracle instead of SQL
server database, all we need to do is implement an OracleRepository that knows how to read and
write to Oracle database and then tie this new Oracle repository implementation with
the interface IEmployeeRepository. In an unit testing project it is easy to mock and replace
a real repository with a fake implementation. That's it in this video. Thank you for listening.