We can utilize Dapper, an ORM (Object-Relational Mapper) or, more accurately, a Micro ORM, to interface with the database in our projects. Dapper allows us to write SQL statements just like we would in a SQL Server. Dapper works well since it doesn't convert.NET queries into SQL.


Dapper's SQL Injection safety is crucial to know since it allows us to perform parameterized queries, which is something we should do at all times. The fact that Dapper supports a variety of database providers is another crucial factor. In order to query our database, it offers helpful extension methods that extend ADO.NET's IDbConnection. Writing queries that work with our database provider is a must, of course.

Company.cs
using System.ComponentModel.DataAnnotations;

namespace DapperApp.Model
{
    public class Company
    {
        public int Id { get; set; }

        [Display(Name = "Company Name")]
        [Required(ErrorMessage = "Company Name is required")]
        public string CompanyName { get; set; }

        [Display(Name = "Company Address")]
        [Required(ErrorMessage = "Company Address is required")]
        public string CompanyAddress { get; set; }

        [Required(ErrorMessage = "Country is required")]
        public string Country { get; set; }

        [Display(Name = "Glassdoor Rating")]
        [Range(1, 5, ErrorMessage = "Glassdoor Rating must be between 1 and 5")]
        public int GlassdoorRating { get; set; }
    }
}

HomeController.cs
using Dapper;
using DapperApp.Model;
using DapperApp.Repository;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Data;

namespace DapperApp.ControllerApp
{
    public class HomeController : Controller
    {
        readonly IGenericRepository _genericController;

        public HomeController(IGenericRepository genericController)
        {
            _genericController = genericController;
        }
        // GET: HomeController
        public async Task<IActionResult> Index()
        {
            var query = "SELECT * FROM Companies";

            var companies = await _genericController.GetData<Company>(query);
            return View(companies);
        }

        // GET: HomeController/Details/5
        public async Task<IActionResult> Details(int id)
        {
            var query = "SELECT * FROM Companies WHERE Id = @Id";
            if (id == null)
            {
                return NotFound();
            }

            var company = await _genericController.GetDataById<Company>(query, id);
            if (company == null)
            {
                return NotFound();
            }

            return View(company);
        }

        // GET: HomeController/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: HomeController/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("Id,CompanyName,CompanyAddress,Country,GlassdoorRating")] Company company)
        {
            var parameters = new DynamicParameters();
            parameters.Add("CompanyName", company.CompanyName, DbType.String);
            parameters.Add("CompanyAddress", company.CompanyAddress, DbType.String);
            parameters.Add("Country", company.Country, DbType.String);
            parameters.Add("GlassdoorRating", company.GlassdoorRating, DbType.Int32);
            var query = "INSERT INTO Companies (CompanyName, CompanyAddress, Country,GlassdoorRating) VALUES (@CompanyName, @CompanyAddress, @Country, @GlassdoorRating)";

            if (ModelState.IsValid)
            {
                await _genericController.CreateData(query, parameters);
                return RedirectToAction("Index");
            }
            return View(company);
        }


        // GET: HomeController/Edit/5
        public ActionResult Edit(int id)
        {
            return View();
        }

        // POST: HomeController/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("Id,CompanyName,CompanyAddress,Country,GlassdoorRating")] Company company)
        {
            if (id != company.Id)
            {
                return NotFound();
            }
            var parameters = new DynamicParameters();
            parameters.Add("CompanyName", company.CompanyName, DbType.String);
            parameters.Add("CompanyAddress", company.CompanyAddress, DbType.String);
            parameters.Add("Country", company.Country, DbType.String);
            parameters.Add("GlassdoorRating", company.GlassdoorRating, DbType.Int32);
            parameters.Add("Id", company.Id, DbType.Int32);
            var query = "UPDATE Companies SET CompanyName = @CompanyName, CompanyAddress = @CompanyAddress, Country = @Country, GlassdoorRating = @GlassdoorRating WHERE Id = @Id";

            if (ModelState.IsValid)
            {
                await _genericController.UpdateData(query, parameters);
                return RedirectToAction("Index");
            }

            return View(company);
        }

        // GET: HomeController/Delete/5
        public ActionResult Delete(int id)
        {
            return View();
        }

        // POST: HomeController/Delete/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var query = "DELETE FROM Companies WHERE Id = @Id";
            await _genericController.DeleteData(query, id);
            return RedirectToAction("Index");
        }
    }
}

DapperContext.cs

using System.Data;
using Microsoft.Data.SqlClient;

namespace DapperApp.Context
{
    public class DapperContext
    {
        private readonly IConfiguration _configuration;
        private readonly string _connectionString;
        public DapperContext(IConfiguration configuration)
        {
            _configuration = configuration;
            _connectionString = _configuration.GetConnectionString("DefaultConnection");
        }

        public IDbConnection CreateConnection() => new SqlConnection(_connectionString);
    }
}

IGenericRepository.cs

using DapperApp.Model;

namespace DapperApp.Repository
{
    public interface IGenericRepository
    {
        Task CreateData(string query, DynamicParameters parameters);
        Task DeleteData(string query, int id);
        Task<T> GetDataById<T>(string query, int id);
        Task<IEnumerable<T>> GetData<T>(string SQL, string DbName = "TEST");
        Task UpdateData(string query, DynamicParameters parameters);
    }
}

C#

GenericRepository.cs

using DapperApp.Context;
using DapperApp.Model;
using DapperApp.Repository;
using Dapper;
using Microsoft.Data.SqlClient;
using System.Data;

namespace DapperApp.Repository
{
    public class GenericRepository: IGenericRepository
    {
        readonly DapperContext _context;

        public GenericRepository(DapperContext context)
        {
            this._context = context;
        }

        public async Task<IEnumerable<T>> GetData<T>(string SQL, string DbName = "TEST")
        {

            using (var connection = _context.CreateConnection())
            {
                var companies = await connection.QueryAsync<T>(SQL);
                return companies.ToList();
            }
        }
        public async Task<T> GetDataById<T>(string query, int id)
        {
            using (var connection = _context.CreateConnection())
            {
                var company = await connection.QuerySingleOrDefaultAsync<T>(query, new { id });
                return company;
            }
        }

        public async Task CreateData(string query, DynamicParameters parameters)
        {

            using (var connection = _context.CreateConnection())
            {
                await connection.ExecuteAsync(query, parameters);
            }
        }

        public async Task UpdateData(string query, DynamicParameters parameters)
        {

            using (var connection = _context.CreateConnection())
            {
                await connection.ExecuteAsync(query, parameters);
            }
        }


        public async Task DeleteData(string query, int id)
        {
            using (var connection = _context.CreateConnection())
            {
                await connection.ExecuteAsync(query, new { id });
            }
        }

    }
}