Использование Dapper в ASP.NET WEB API 2 приложении
Dapper.NET — это «mini-ORM» на которой работает движок StackExchange и сайт StackOverflow в частности. Dapper это технология маппинга результатов sql-запросов с классами c#. Dapper чем то похож на Entity Framework, но за счет легковесности Dapper обеспечивает большую производительность и работает быстрее, нежели Entity Framework.
Далее рассмотрим как можно построить REST'ful api controller с запросами к базе через dapper.
1. Создаем class library для Dapper'a
2. Подключаем Dapper с nuget'a
3. Создаем WebApi проект в visual studio
Теперь когда у нас есть каркас, мы можем приступить к созданию базы данных.
4. Создание базы
- Переходим в SQL Management Studio
- Нажимаем правой кнопкой на базы данных и выбираем создать новую
- Вводим название новой базы (например Dapper) и нажимаем ОК.
5. Создаем таблицу "Книги"
для этого выполним следующий sql скрипт:
CREATE TABLE Books (
Id int NOT NULL IDENTITY,
Author nvarchar(100) NOT NULL,
Name nvarchar(250) NOT NULL,
PageCount int,
PRIMARY KEY (Id)
);
Теперь когда наша база готова, можем приступать к программированию.
5. Создаем класс Book
namespace Dapper.Entities
{
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public int PageCount { get; set; }
}
}
6. Создаем репозиторий для Book
Для класса книга, теперь можно создать репозиторий который будет выполнять CRUD операции.
Создаем интерфейс IBookRepository
using System.Collections.Generic;
using Dapper.Entities;
namespace Dapper.Repositories
{
public interface IBookRepository
{
void Create(Book book);
void Delete(int id);
Book Get(int id);
IEnumerable<Book> GetAllBooks();
void Update(Book book);
}
}
И его реализацию BookRepository
using System.Collections.Generic;
using System.Data;
using Dapper.Entities;
using System.Data.SqlClient;
using System.Linq;
using System.Configuration;
namespace Dapper.Repositories
{
public class BookRepository : IBookRepository
{
private readonly string _connectionString = ConfigurationManager.ConnectionStrings["DapperConnection"].ConnectionString;
public IEnumerable<Book> GetAllBooks()
{
using (IDbConnection db = new SqlConnection(_connectionString))
{
return db.Query<Book>("SELECT * FROM Books");
}
}
public Book Get(int id)
{
using (IDbConnection db = new SqlConnection(_connectionString))
{
return db.Query<Book>("SELECT * FROM Books WHERE Id = @id", new { id }).FirstOrDefault();
}
}
public void Create(Book book)
{
using (IDbConnection db = new SqlConnection(_connectionString))
{
var sqlQuery = "INSERT INTO Books (Name, Author, PageCount) VALUES(@Name, @Author, @PageCount); SELECT CAST(SCOPE_IDENTITY() as int)";
int userId = db.Query<int>(sqlQuery, book).First();
book.Id = userId;
}
}
public void Update(Book book)
{
using (IDbConnection db = new SqlConnection(_connectionString))
{
var sqlQuery = "UPDATE Books SET Name = @Name, Author = @Author, PageCount = @PageCount WHERE Id = @Id";
db.Execute(sqlQuery, book);
}
}
public void Delete(int id)
{
using (IDbConnection db = new SqlConnection(_connectionString))
{
var sqlQuery = "DELETE FROM Books WHERE Id = @id";
db.Execute(sqlQuery, new { id });
}
}
}
}
Следует заметить, что мы используем DapperConnection connectionstring.
Добавим ее в webapi проект в web.config.
<add name="DapperConnection" connectionString="Data Source=localhost;Initial Catalog=Dapper;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
7. Переходим к созданию API BooksController'y
using Dapper.Repositories;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web.Http;
using Dapper.Entities;
namespace WebApiTest.Controllers
{
public class BooksController : ApiController
{
private readonly IBookRepository _bookRepository = new BookRepository();
// GET: api/Books
public async Task<IEnumerable<Book>> Get()
{
return _bookRepository.GetAllBooks();
}
// GET: api/Books/5
public Book Get(int id)
{
return _bookRepository.Get(id);
}
// POST: api/Books
public IHttpActionResult Post([FromBody]Book book)
{
_bookRepository.Create(book);
return Created(Request.RequestUri + book.Id.ToString(), book);
}
// PUT: api/Books/5
public IHttpActionResult Put(int id, [FromBody]Book book)
{
book.Id = id;
_bookRepository.Update(book);
return Ok();
}
// DELETE: api/Books/5
public IHttpActionResult Delete(int id)
{
_bookRepository.Delete(id);
return Ok();
}
}
}
Следует отметить, что строчка private readonly IBookRepository _bookRepository = new BookRepository(); к использованию не желательна, тут она продемонстрирована ислючительно в качестве примера, я рекомендую использовать какой-то IoC контейнер и инджектить IBookRepository в конструктор.
Наш RESTful API готов к использованию, давайте протестируем его через постмен и посмотрим что получилось.
Добавление книги
Обновление записи книга
Получение списка книг
Получение книги по id
Удаление книги
Итог:
Dapper это отличный инстумент который подойдет для высоконагруженных и посещаемых enterprise проектов таких как stackexchange. В остальных случаях Entity Framework отлично справляется с задачей основной ORM. Но она требует правильных настроек и правильного подхода к использованию и оптимизации. Если у вас есть достаточно высоконагруженные системы или запросы в них, можно приминять Dapper для оптимизации этих запросов (или же в EF использовать команду SqlQuery и писать чистый sql) так как Dapper работает в разы быстрее остальных ORM.