Dapper

Работа с Dapper в ASP.NET Core

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 29.12.2019

Dapper представляет собой инструмент от компании Stack Exchange, который сопоставляет результаты sql-запросов с классами c#. В этом плане Dapper немного похож на Entity Framework. Однако за счет своей легковесности Dapper обеспечивает большую производительность и быстрее позволяет выполнять запросы, чем EF Core. В частности, dapper применяется в работе сайта stackoverflow.com.

Исходные коды dapper, а также ряд дополнительнйо информации по библиотеке можно найти на официальном репозитории на https://github.com/StackExchange/Dapper.

Для работы с Dapper создадим новый проект ASP.NET Core по типу ASP.NET Core Web App (Model-View-Controller). И вначале добавим в него через Nuget пакеты Microsoft.Data.SqlClient и Dapper (при работе с Dapper используется функционал пакета Microsoft.Data.SqlClient):

Установка Dapper в ASP.NET Core

Затем определим модель User, с которой мы будем работать:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

Для работы с Dapper создадим на MS SQL Server небольшую базу данных, которую назовем userstore. Далее в этой базе данных определим одну таблицу, которая соответствует описанию модели User и имеет три поля Id, Name и Age:

База данных для Dapper в ASP.NET Core

Затем также добавим в папку Models интерфейс и класс репозитория, через который будем работать с базой данных:

using Dapper;
using System.Collections.Generic;
using System.Data;
using Microsoft.Data.SqlClient;
using System.Linq;

namespace DapperMvcApp.Models
{
    public interface IUserRepository
    {
        void Create(User user);
        void Delete(int id);
        User Get(int id);
        List<User> GetUsers();
        void Update(User user);
    }
    public class UserRepository : IUserRepository
    {
        string connectionString = null;
        public UserRepository(string conn)
        {
            connectionString = conn;
        }
        public List<User> GetUsers()
        {
            using (IDbConnection db = new SqlConnection(connectionString))
            {
                return db.Query<User>("SELECT * FROM Users").ToList();
            }
        }

        public User Get(int id)
        {
            using (IDbConnection db = new SqlConnection(connectionString))
            {
                return db.Query<User>("SELECT * FROM Users WHERE Id = @id", new { id }).FirstOrDefault();
            }
        }

        public void Create(User user)
        {
            using (IDbConnection db = new SqlConnection(connectionString))
            {
                var sqlQuery = "INSERT INTO Users (Name, Age) VALUES(@Name, @Age)";
                db.Execute(sqlQuery, user);

                // если мы хотим получить id добавленного пользователя
                //var sqlQuery = "INSERT INTO Users (Name, Age) VALUES(@Name, @Age); SELECT CAST(SCOPE_IDENTITY() as int)";
                //int? userId = db.Query<int>(sqlQuery, user).FirstOrDefault();
                //user.Id = userId.Value;
            }
        }

        public void Update(User user)
        {
            using (IDbConnection db = new SqlConnection(connectionString))
            {
                var sqlQuery = "UPDATE Users SET Name = @Name, Age = @Age WHERE Id = @Id";
                db.Execute(sqlQuery, user);
            }
        }

        public void Delete(int id)
        {
            using (IDbConnection db = new SqlConnection(connectionString))
            {
                var sqlQuery = "DELETE FROM Users WHERE Id = @id";
                db.Execute(sqlQuery, new { id });
            }
        }
    }
}

Для осуществления запросов Dapper предоставляет для объектов IDbConnection метод расширения Query<T>, который в качестве параметра принимает sql-выражение и может возвращать объект типа T, с которым сопоставляются результаты запроса.

Если нужно просто выполнить запрос без необходимости возвращать результат, как в случае с добавлением, обновлением, удалением, то можно использовать метод Execute, в который передается sql-выражение и набор параметров для этого выражения.

Далее изменим файл Startup.cs:

using DapperMvcApp.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace DapperMvcApp
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            string connectionString = "Server=.\\SQLEXPRESS;Initial Catalog=userstore;Integrated Security=True";
            services.AddTransient<IUserRepository, UserRepository>(provider => new UserRepository(connectionString));
            services.AddControllersWithViews();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseDeveloperExceptionPage();

            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

С помощью механизма внедрения зависимостей здесь устанавливается зависимость для интерфейса IUserRepository в виде объекта UserRepository, в конструктор которого передается строка подключения к бд.

В этом случае контроллер HomeController для взаимодействия с бд и выполнения всех базовых CRUD-операций мог бы выглядеть следующим образом:

using Microsoft.AspNetCore.Mvc;
using DapperMvcApp.Models;

namespace DapperMvcApp.Controllers
{
    public class HomeController : Controller
    {
        IUserRepository repo;
        public HomeController(IUserRepository r)
        {
            repo = r;
        }
        public ActionResult Index()
        {
            return View(repo.GetUsers());
        }

        public ActionResult Details(int id)
        {
            User user = repo.Get(id);
            if (user != null)
                return View(user);
            return NotFound();
        }

        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(User user)
        {
            repo.Create(user);
            return RedirectToAction("Index");
        }

        public ActionResult Edit(int id)
        {
            User user = repo.Get(id);
            if (user != null)
                return View(user);
            return NotFound();
        }

        [HttpPost]
        public ActionResult Edit(User user)
        {
            repo.Update(user);
            return RedirectToAction("Index");
        }

        [HttpGet]
        [ActionName("Delete")]
        public ActionResult ConfirmDelete(int id)
        {
            User user = repo.Get(id);
            if (user != null)
                return View(user);
            return NotFound();
        }
        [HttpPost]
        public ActionResult Delete(int id)
        {
            repo.Delete(id);
            return RedirectToAction("Index");
        }
    }
}

Представления в этом случае могли бы выглядеть следующим образом. Представление Index.cshtml для вывода списка пользователей:

@model IEnumerable<DapperMvcApp.Models.User>
@{
    ViewData["Title"] = "Список пользователей";
}
<h2>@ViewData["Title"]</h2>
<p>
    <a asp-controller="Home" asp-action="Create">Добавить</a>
</p>
<table class="table">
    <tr>
        <th>Имя</th>
        <th>Возраст</th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>@item.Name</td>
            <td>
                @item.Age
            </td>
            <td>
                <a asp-controller="Home" asp-action="Edit" asp-route-id="@item.Id">Изменить</a> |
                <a asp-controller="Home" asp-action="Delete" asp-route-id="@item.Id">Удалить</a>
            </td>
        </tr>
    }
</table>

Представление Create.cshtml для добавления пользователей:

@model DapperMvcApp.Models.User

@{
    ViewData["Title"] = "Новый пользователь";
}
<h2>@ViewData["Title"]</h2>

<form asp-action="Create" asp-controller="Home">
    <div>
        <div class="form-group">
            <label asp-for="Name"></label>
            <input type="text" asp-for="Name" class="form-control form-control-sm" />
        </div>
        <div class="form-group">
            <label asp-for="Age"></label>
            <input asp-for="Age" class="form-control  form-control-sm" />
        </div>
        <div class="form-group">
            <input type="submit" value="Сохранить" class="btn btn-outline-secondary" />
        </div>
    </div>
</form>

<div>
    <a asp-controller="Home" asp-action="Index">Вернуться к списку</a>
</div>

Представление Edit.cshtml для редактирования пользователей:

@model DapperMvcApp.Models.User
@{
    ViewData["Title"] = "Редактировать пользователя";
}
<h2>@ViewData["Title"].</h2>

<form asp-action="Edit" asp-controller="Home">
    <div>
        <input type="hidden" asp-for="Id" />
        <div class="form-group">
            <label asp-for="Name"></label>
            <input type="text" asp-for="Name" class="form-control" />
        </div>
        <div class="form-group">
            <label asp-for="Age"></label>
            <input asp-for="Age" class="form-control" />
        </div>
        <div class="form-group">
            <input type="submit" value="Сохранить" class="btn btn-outline-secondary" />
        </div>
    </div>
</form>

<div>
    <a asp-controller="Home" asp-action="Index">Вернуться к списку</a>
</div>

И представление Delete.cshtml для удаления пользователя:

@model DapperMvcApp.Models.User
@{
    ViewData["Title"] = "Удаление пользователя";
}
<h2>@ViewBag.Title</h2>
<div>
    <dl class="dl-horizontal">
        <dt>Имя</dt>
        <dd>
            @Model.Name
        </dd>

        <dt>Возраст</dt>
        <dd>
            @Model.Age
        </dd>
    </dl>

    <div>
        <form asp-controller="Home" asp-action="Delete" method="post">
            <div class="form-group">
                <input type="submit" class="btn btn-default" value="Удалить" />
            </div>
        </form>
    </div>
</div>

Запустим приложение и добавим пользователя:

CRUD Dapper in ASP.NET Core MVC

Затем мы его сможем увидеть в списке пользователей:

Операции с базой данных через Dapper в ASP.NET Core MVC
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850