.NET - Dapper ORM İçin Generic Repository Oluşturulması

Herkese merhaba,

Bu yazımda Dapper Generic Repository yapısını nasıl kuracağımıza değineceğim. Mevcut bir ORM aracını değiştirip Dapper için de generic repository yapmak isteyebiliriz. İnternette Dapper Generic Repository yapısını dinamik görmemem; bu yazıyı yazmamda motivasyon kaynağı oldu. 

Ön bilgi olması açısından kullanacağımız nuget paketimiz, Dapper.Contrib'dir. Bu paket, temel CRUD işlemleri için helper metotlar içerir. Paketin içeriğinde Dapper paketi de mevcuttur. Dapper kütüphanesi de kendiliğinden gelecektir.

Dapper.Contrib paketini resmi dokümantasyonunu detaylı incelemek için linke tıklayınız. 

Ayrıca Dapper.Contrib.Extensions nuget paketini de entity model sınıflarında veri tabanı tablosunu eşleştrmek ve primary key olan property için annotation eklemek için de yüklememiz gerekir.

Paketlerimizi anladıktan sonra Generic Repository yapısını kurmaya başlayabiliriz. Temel CRUD operasyonlarımızı içerecek generic bir IEntityRepository interface oluşturuyoruz. Farklı ORM ve teknolojilerde uygun geliştirme yapılabilir. Bu yazı özelinde Dapper için bu interfacedeki metotları kullanacak bir sınıf oluşturacağız.

DapperGenericRepository sınıfı da IEntityRepository interfacesini miras alacak generic bir yapıdadır. Metotları implement ederken, Dapper.Contrib.Extensions paketindeki metotları kullandık.  

Metotları oluştururken using bloklarında, önceden oluşturduğum DbConnect sınıfındaki Connection propertysini kullandım. İşlevi, appsettings.json dosyasını build edip connection stringi almaya yarar. Connection oluşturduktan sonra Dapper sorgularını yapabiliyoruz. Connection Stringimizde veri tabanı olarak Northwind kullandık.

Generic Repository yapısını oluşturduktan sonra kullanım aşamasına geçiyoruz. DataAccess katmanında Abstract interface ve Concrete sınıflar oluşturuyoruz. Concrete sınıflar, kullanacağımız ORM veya teknolojilere göre değişebilir. Dapper için veri erişim işlemleri, Dapper klasörü altında yapılacaktır. Her bir entity için sınıflar oluşturuldu. 


Örneğin, IProductDal interfacesi, mevcut CRUD işlemlerinin yanı sıra Product entity'i için veri erişim işlemlerini tutar.  IEntityRepository<Product> generic repository interface'yi miras alır. Farklı entity için farklı metotlar ekleyebiliriz veya eklemeden boş bırakabiliriz. 

DapperProductDal ise IProductDal interfacesinde eklenen metotların Dapper ORM'e göre doldurulduğu yerdir. Metot, Dapper'daki Query metodu kullanılarak GetAllProductsByCategoryId  stored procedure ismi Query metodunda ilk parametre olarak gönderiliyor. Bir sonraki parametreye gönderilen kategori id'ye göre ürünlerin listelenmesi yapılacaktır.

DataAccess katmanında oluşturulan metotları, Business katmanında çağıracağız. IProductService interfacesinden miras alan ProductManager sınıfı, bizim Product entity için iş yapan metotları barındıracaktır. IProductDal ile bağımlılık enjekte edilecektir. 


IProductService interfacesinde metotlar tanımlandı. 

ProductManager.cs implementasyonu görünümü aşağıdaki gibidir.

Models katmanında entity objelerimiz bulunuyor. Northwind veri tabanındaki tablolar için sınıflar oluşturuldu. Products tablosuna karşılık gelen Product sınıfı oluşturuldu.


Product sınıfında ProductId property için Key olarak tanımlanmasının mantığı, ilgili veri tabanı tablosundaki primary key olan ProductId'yi vermektedir. Belirtilmezse hata verecektir.

Table attribute olarak tanımlanan değer, Northwind veri tabanındaki Products tablosuna karşılık gelecektir. Eğer eşleştirme doğru yapılmadığında geçersiz obje adı şeklinde hata verecektir. 

Örneklerde Key ve Table olarak açıklanan attributeler, Dapper.Contrib paketinde Data Annotations olarak geçer ve mapping işleminin doğru bir şekilde yapılmasını sağlar.

UnitTest'te DapperProductTests sınıfında Product için örnek testler hazırlandı. Aşağıdaki ekran görüntülerinde çıktıları görebilirsiniz.




Dapper ORM için Generic Repository yapısının tamamını .NET 6 üzerinde çalışan örnek repomda bulabilirsiniz. 

Github Repo Linkni incelemek için tıklayınız.

Yorumlar