Introduction
The main advantages of using design pattern are to keep the modules loosely coupled and to help developers address
change requests with minimal changes to the code. Also, the modules can be reusable in multiple projects, which speeds up development. There are many design patterns, and one advantage of using the repository design pattern is to
keep the data access logic centralized.
Initially, I struggled to understand both why
we need AutoMapper and how to configure dependency injections in .NET CORE. But
I received help from a senior architect, so now I am able to understand the
complete data flow. I know there are many articles on this topic, but they may
not answer all your questions and requirements.
In this article, I'm going to explain the data
flow so that you can understand it as well.
Step 1 - Create a New API Project in VS
In Visual Studio, click on File, go to New, and select the appropriate
project template.
Click on OK. This opens up a new dialog. Select API and uncheck
“configure HTTPS” for now. Click on OK.
It creates a project and structure that looks like this.
Step 2 - Create a New Class Library Project for Data
Right click on your solution. Go to Add, and select New Project.
Select the Class Library project and Click OK.
Next, create a database in the SQL Server and create a test table with a
few columns as shown below.
How to Connect Your SQL DB With Your .NET Core Application
Next we need to scaffold the SQL database by running a command.
Click on Tools, go to NuGet Package Manager, and select Package Manager
Console.
Run the below command. Before running this command make sure that
you’ve selected “Data Class Library Project” in the top dropdown of the package
manager console.
- Scaffold-DbContext "Server=tcp:xxxxxserver.database.windows.net;Database=xxxx_dev;User Id=xxxxxxx;Password=xxxxxx" Microsoft.EntityFrameworkCore.SqlServer -Context CsharpCornerContext -Force
This will create your DBContext class and all the other table objects.
Open the created context file and remove the constructors without parameters
with the OnConfiguring method.
Next you need to create a DBContextPool in your API Project.
Go to your API Project and open the startup.cs file. Modify the
ConfigureService method and create the DBContextPool like below.
- services.AddEntityFrameworkSqlServer();
- services.AddDbContextPool<CsharoCornerContext>((serviceProvider, options) => { options.UseSqlServer(Configuration.GetConnectionString("connStr")); });
The connection string is added in appsettings.json and referenced here.
Note
If you get any error with UseSqlServer, then import manually using
Microsoft.EntityFrameworkCore.
Step 3 - Create a New Class Library Project for the Repository
Follow the above steps to create a class library project.
Next, create a DBHelper Class (optional). Create a repository class
named “Common Repository.”
Next, inject your DBContext (and DBHelper if you configured it) into
your repository as shown below.
- class CommonRepository : ICommonRepository
- {
- private readonly IDBHelper dBHelper;
- private CsharoCornerContext csharoCornerContext;
-
- public CommonRepository(IDBHelper dBHelper, CsharoCornerContext csharoCornerContext)
- {
- this.csharoCornerContext = csharoCornerContext;
- this.dBHelper = dBHelper;
- }
- }
Create a common controller in your API Project.
- [Route("api/[controller]")]
- [ApiController]
- public class CommonController : ControllerBase
- {
- }
Inject your common repository into a common controller as shown below.
- [Route("api/[controller]")]
- [ApiController]
- public class CommonController : ControllerBase
- {
- private ICommonRepository commonRepository;
- public CommonController(ICommonRepository commonRepository)
- {
- this.commonRepository = commonRepository;
- }
- }
Next we need to configure the repository in the startup.cs file of the
API Project.
Add the below two lines in your ConfigurationService method.
- services.AddScoped<ICommonRepository, CommonRepository>();
- services.AddScoped<IDBHelper, DBHelper>();
Step 4 - Create a Class Library Project for Models, DTO, and ResultSet
Follow the same steps as above to create your class library
project.
Models are used to get data from users, which is the payload for an API.
DTO is used to transfer
data from one layer to another layer (from the controller to the repository).
ResultSet is used to perform DB operations.
After creating a separate class library project for each one of the
above, the structure looks like below.
Step 5 - Create a Class Library Project for AutoMapper
Follow the same steps as above to create a class library project.
We need to install AutoMapper, which is a simple little library built to
solve a deceptively complex problem -- getting rid of code that has mapped one
object to another.
- PM> Install-Package AutoMapper
Right click on Project and create a mapping class and
inherit profile using AutoMapper. The code looks like below.
- using AutoMapper;
- using System;
- using System.Collections.Generic;
- using System.Text;
-
- namespace CsharpCornerDemo.Mapping
- {
- public class Mappers : Profile
- {
- public Mappers()
- {
-
- }
- }
- }
Next, we need to configure AutoMapper in the API Project and create a
singleton instance of it.
Open Startup.cs file and modify the ConfigurationService method like
below.
Note: You need to install AutoMapper.
- var mappingConfiguration = new MapperConfiguration(config => config.AddProfile(new Mappers()));
- IMapper mapper = mappingConfiguration.CreateMapper();
- services.AddSingleton(mapper);
Step 6 - Write an API to Connect All Layers
Let’s write an API to get data fromTesttbl.
First, create a ResultSet and DTO for Testtbl.
Inject mappers in the repository and the controller. It looks like this.
- public class CommonRepository : ICommonRepository
- {
- private readonly IDBHelper dBHelper;
- private CsharoCornerContext csharoCornerContext;
- private IMapper mapper;
-
- public CommonRepository(IDBHelper dBHelper, CsharoCornerContext csharoCornerContext, IMapper mapper)
- {
- this.csharoCornerContext = csharoCornerContext;
- this.dBHelper = dBHelper;
- this.mapper = mapper;
- }
- }
Create a method to get the test data in a common
repository like below, calling
Stored Procedure.
- public IEnumerable<TestDTO> GetTestData()
- {
- var result = csharoCornerContext.Query<TestResultSet>().FromSql("dbo.TestData").ToList();
- return mapper.Map<List<TestDTO>>(result);
- }
Create an API in the common controller and call the GetTestData method.
- [HttpGet("test")]
- [ProducesResponseType(200)]
- [ProducesResponseType(400)]
- public async Task<IActionResult> GetTestData()
- {
- try
- {
-
- var test = await Task.FromResult(commonRepository.GetTestData());
- return Ok(test);
- }
- catch
- {
- return BadRequest("Could not fetch test data");
- }
- }
Also, we need to add mappers.
- public class Mappers : Profile
- {
- public Mappers()
- {
- CreateMap<TestResultSet, TestDTO>();
- }
- }
Let's test the API.
Summary
In this article, we discussed how to use repository design pattern in a
.NET CORE Web API, as well as how to use AutoMapper. I hope this article was
useful, and that you now have a better understanding of the data flow.