In today's video, we'll talk about the repository
pattern. We will learn the benefits of using it and how to implement it. We will use c# and
asp.net but the topic is relevant to any programming language. My name is Pat, if you are
new here consider subscribing. Let's get into it. Allow me to introduce this small application
that helps me manage a book library, I can add a new book by providing a title, the author,
a category, and the date of the publication of the book. if I click on the create button the
book is saved in a database. I also have a section to manage authors and another one to manage
different book categories. This application was created with Asp.net MVC, Entity Framework Core as
the data access layer, and SQLite as the database. Let's take a look at the structure of the
project, we have controllers, models, views, and so on, a typical MVC application. As you have
seen in the demo, the application is working, however, it faces three problems that we
will discuss, problem number: 1 tie coupling All the controllers receive a book context
as a dependency in the constructor, they use the context to retrieve or change data
in the database, the context object is specific to entity framework, if one day we choose to use
another product like Dapper or NHibernate for instance, we won't need it anymore, that means
we will have to go in every places the context is used and replace it with some new code, that
can lead to introducing bugs in the application. So, tie coupling makes it hard to change the
code. Let's talk about the second problem. Problem number 2: duplication. When we need to
insert a new book, we have to select an author from a list, the book controller gets a
list of author sorted by the last name in order to display them in a drop-down list,
the author's controller also gets the same data in order to display them in the author view, when
using the context straight into the controller, we easily end up with duplicate code. Imagine if
we need some transformation on the author list, we will have to go to each location where
the list is used in order to update the code. Duplication makes it hard to change the code.
Let's talk about the last problem, if we want to test the books controller, for instance,
we will have a problem because the controller depends on the context object, that means we will
perform real operations against the database, that's something you don't want to do when
testing, you want the controller to depend on some abstraction so when testing you can mark
the abstraction. Those were the three problems with the current state of the application. How to
change the code to make it less couple, reusable, and testable? the answer is the repository
pattern. The repository is a layer that will sit between the controller and the data access
layer, the controller will no longer depend on the data access layer but instead on a repository
interface. Usually, you create a repository per entity, we have three entities, we will create
three repositories. All repositories will inherit from the same interface because they all need the
same method. Let's start by creating a generic interface, we create a folder named repositories
then we had an interface called IRepository, this repository has two generic types
T1 and T2, T1 has a constraint that says that the type must be a class, like book,
category or author. T2 is the type of primary key that will be used in some method like get by
id or delete. Let's add all the methods we need. "GetAll" will fetch all data, if the repository
is used with book as a T1 parameter then this will fetch all the books, "GetById" will
retrieve a single record given its id, "Create" we insert a record in the
database, "Delete" will remove a record. and "Save" will apply changes to the database. Now, let's add a concrete implementation
of the repository. In the repositories folder, we add a new class called book repository, this class
implements the IRepository interface, the first parameter is the book type because a repository
will manage books, and the second is int which is the type of our primary key. The repository uses
the book context to communicate with the database Each method use the DbSet to perform operations
against the database, let's look at the "GetAll" method, for instance, I used the "ToListAsync"
method on the DbSet property to fetch all data, and I load related data by using the
include method. In the "GetById", we use the "FindAsync" method on the DbSet to
retrieve a single book. In the insert method, we use the "AddAsync" and give a book as a
parameter to insert it in a database. In the "Delete" method, we first retrieve the book
given its id, if it's found, we delete it. And finally, in the "Save" method,
we persist changes to the database, this method will be invoked after an insert
or a delete. I am going to create the category repository and the author repository, they follow
the same pattern so I see you when I'm done. The repositories are created, so let's
register them with the dependency injection system so we can inject them into the
controllers. In the Startup class, let's update the "ConfigureServices"
method, we register the repositories using the "AddScope" method, this means
that there will be an instance per request. Now, let's refactor the BooksController,
the goal here is to replace each usage of the context with a repository. We
inject the repositories through the constructor, in the Index method for
instance, instead of fetching books using the DbContext, we use the book repository. We do the same in the Create method We refactor also the Delete method In the method that populates the author list, we
use the "GetAll" method from the AuthorRepository to retrieve all authors and in the
method that populates the category list, we use the "GetAll" method from the
CategoryRepository to retrieve all categories. Let's test the application
to see if it's still working Yes, it's still working,
let's see if I can add a book The book has been saved to the database, now
I'm going to replace the DbContext in the AuthorController and the CategoriesController,
so they can use the repository instead, the process is the same as in BooksController,
so i see you after the refactoring. The refactoring is done let's test the app again. It's still working, but now, the controllers
use a repository instead of the DbContext. This tutorial stops here. We learn how the
repository pattern makes the code easy to change, less coupled, and testable. Despite all
the benefits we get from the pattern, it adds a layer of complexity, use
the pattern when it makes sense if you work on a tiny project for
instance maybe you don't need it. If you enjoyed this tutorial, feel free to like
the video, drop a comment in the comment section, and subscribe to the channel so you don't miss
future videos. Thanks for watching, see you soon.