Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
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):
Затем определим модель 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:
Затем также добавим в папку 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>
Запустим приложение и добавим пользователя:
Затем мы его сможем увидеть в списке пользователей: