Object relational mappers (ORMs); ilişkisel veritabanları ile programlama dillerinin nesne modelleri arasındaki uyumsuzluğu ortadan kaldırmak, kod ile database arasındaki uyumu %100 sağlamak için yazılım dünyasında uzun süredir kullanılmaktadırlar. Daha önceki ORM yazımızda Fluent NHibernate Nedir ve Kullanımı konusuna değinmiştik. Bu yazımızda ise birçok kişi tarafından en hızlı ORM olarak kabul edilen Dapper'ı inceleyeceğiz.
Dapper, Stack Overflow ekibi tarafından open-source geliştirilen lightweight bir ORM'dir. Lightweight olması sebebiyle diğer ORM'lere kıyasla çok daha hızlıdır.
Dapper, performans ve kullanım kolaylığı sağlaması düşünülerek geliştirilmiş bir ORM dir. Transaction, stored procedure yada bulk insery kullanarak static ve dynamic object binding yapabilmemizi sağlar.
Dapper Kullanımı
Dapper kullanımı için örnek basit bir app. geliştirelim. İlk olarak Vs'da Dapper_Sample adında bir ConsoleApp oluşturalım. Sonrasında nuget üzerinden Dapper'ı projemize indirip kuralım.
Install-Package Dapper -Version
Kurulum işlemi tamamlandıktan sonra örneğimiz şu şekilde olsun; ContosoCorp adında bir db ve bu db de Customer adında bir tablomuz olsun ve dapper kullanarak repository class ile bu tablo üzerinde CRUD işlemleri yapalım.
Öncelikle ContosoCorp db si için table create script'ini aşağıdaki gibi yazıp execute edelim ve Customer tablomuz oluşturalım.
create table Customer
(
Id uniqueidentifier,
FirstName nvarchar(50) not null,
LastName nvarchar(50) not null,
Email nvarchar(50) not null
)
İlk olarak tablomuza karşılık gelen Customer entity'sini aşağıdaki gibi oluşturalım.
public class Customer
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
Şimdi ise CRUD işlemleri için CustomerRepository adında bir class oluşturalım ve içerisini CRUD metotlarını tanımlayalım.
public class CustomerRepository
{
protected SqlConnection GetOpenConnection()
{
var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ContosoCorpDbConn"].ConnectionString);
connection.Open();
return connection;
}
}
Config dosyamızda kullanacağımız db için gerekli olan conn. string'inin ContosoCorpDbConn adıyla yazılı olduğunu varsayalım ve GetOpenConnection() metodu ile repository metotlarında kullanacağımız SqlConnection yaratacağız.
Dapper'da bulunan Query() metodu veritabanından retrieve data işlemini yani veri almamızı sağlayan ve model mapping'i yaparak modellerimizi dolduran metoddur. Aşağıda yazacağımız All() metodu ile Customer tablosunda bulunan bütün kayıtları select edeceğiz.
public IEnumerable<Customer> All()
{
using (var conn = GetOpenConnection())
{
return conn.Query<Customer>("Select * From Customer").ToList();
}
}
İkinci metot olarak Id parametresi alarak geriye tek bir Customer objesi return eden Get() metodunu yazalım.
public Customer Get(Guid id)
{
using (var conn = GetOpenConnection())
{
return conn.Query<Customer>("Select * From Customer WHERE Id = @Id", new { id }).SingleOrDefault();
}
}
Dapper'da bulunan Execute() metodu ise db de insert, update veya delete işlemlerinde kullanılır. Aşağıda yazacağımız metot ile parametre olarak verilen customer nesnesini insert edeceğiz.
public void Insert(Customer customer)
{
using (var conn = GetOpenConnection())
{
string sqlQuery = "INSERT Customer(FirstName,LastName,Email) Values(@FirstName,@LastName,@Email)";
conn.Execute(sqlQuery, customer);
}
}
Yukarıda görüldüğü üzre ado.net'e aşinalığı olan kişiler aslında bir nevi ado.net yazdığımızı göreceklerdir çünkü dapper'ın temelinde AdoçNet vardır. Son metot olarak dapper ile yukarıda yazdığımız All() metodunu birde stored-procedure kullanarak yazalım. İlk olarak db üzerinden aşağıdaki gibi GetAllCustomersSP adında stored-procedure'ü tanımlayalım.
CREATE PROCEDURE GetAllCustomersSP
AS
BEGIN
SELECT * FROM Customer
END
Sonrasında bu procedure'ü execute eden repository metodunu yazalım.
public IEnumerable<Customer> AllUsingSp()
{
using (var conn = GetOpenConnection())
{
return conn.Query<Customer>("GetAllCustomersSP", commandType: CommandType.StoredProcedure).ToList();
}
}
Repository metotlarını tanımladık sırada bu metotları kullanmak var. Program.cs içerisinde bu metotları call ederek yazdığımız kodları test edelim.
static void Main(string[] args)
{
var custRepo = new CustomerRepository();
var customer1 = new Customer { Id = Guid.NewGuid(), FirstName = "Caner", LastName = "Tosuner", Email = "info@canertosuner.com" };
var customer2 = new Customer { Id = Guid.NewGuid(), FirstName = "Berker", LastName = "Sönmez", Email = "info@berkersonmez.com" };
custRepo.Insert(customer1);
custRepo.Insert(customer2);
//returns 2 records
var allCustomersUsingQuery = custRepo.All();
//returns 2 records
var allCustomersUsingSp = custRepo.AllUsingSp();
Console.ReadLine();
}
Projemizi run ettiğimizde Customer tablosuna sırasıyla 2 kayıt atacaktır ve sonrasında All() ve AllUsingSp() metotlarını kullanarak tabloya select sorgusu yaptığımızda bize yukarıda kaydettiğimiz 2 kaydı return edecektir.
Dapper aynı zamanda transactional işlemleri de destekler. UnitOfWork pattern'i BeginTransaction() ve EndTransaction() metotlarını kullanarak uygulanabilir.
Not : Nuget de bulunan DapperExtensions kütüphanesi kullanarak gerekli mapping işlemlerini yaptıktan sonra repository metotları içerisinde sql komutları yerine aşağıdaki gibi de kullanabiliriz. Not: Bu mapping üzerinden table/column auto generate işlemi olmamakta sadece mapping işlemini sağlamakta.
Install-Package DapperExtensions
public class CustomerMapper : ClassMapper<Customer>
{
public CustomerMapper()
{
base.Table("Customer");
Map(f => f.Id).Key(KeyType.Guid);
Map(f => f.FirstName);
Map(f => f.LastName);
Map(f => f.Email);
}
}
public IEnumerable<Customer> All()
{
using (var conn = GetOpenConnection())
{
return conn.GetList<Customer>().ToList();
}
}
public Customer Get(Guid id)
{
using (var conn = GetOpenConnection())
{
return conn.Get<Customer>(id);
}
}
DapperExtensions kütüphanesi ile kolayca bir Generic Repository Pattern infrastructure'ı geliştirebilirsiniz. Yazının sadeliği açısından bu ben değinmedim ancak sonraki yazılarımızda bir IoC kütüphanesi kullanarak Dapper ile basitçe bir api projesi geliştireceğiz.
Dapper son derece geliştirmesi kolay ve kullanışlı bir ORM dir. NHibernate ve EntityFramework'de olduğu gibi model mapping'inizden table/column generate etmez ancak sql sorgularını oldukça hızlı bir şekilde execute eder ve result'larını POCO class'larınıza map'ler. Bu özelliğiyle developer'lar arasında oldukça popülerdir.