.NET Core Ortamında Onion Architecture ile Dapper Uygulaması

Abdullah Öztürk
4 min readJul 15, 2022

--

Merhaba Arkadaşlar,

Bugün Micro-ORM denilince akla gelen Dapper nedir, nasıl kullanılır, neden tercih edilir gibi soruların cevaplarına değineceğim. Dapper tanımını yaptıktan sonra .NET Core ile Onion Architecture kullanarak bir uygulama geliştirerek pratik yapacağız.

Dapper Nedir?

Dapper, bir sql sorgusunun sonucundaki verileri .NET sınıfı ile ilişkilendirmemizi sağlayan bir Micro-ORM aracıdır. Stackoverflow ekibi tarafından geliştirilmiş olan bu araç, Entity Framework performansıyla karşılaştırıldığında verileri sorgulamada kesinlikle daha hızlıdır. Dapper raw sql ile çalışırken zaman gecikmesi de oldukça azdır. Bu durum Dapper aracının performansını arttırmaktadır.

Dapper Özellikleri

  • Performans açısından hızlı
  • Daha az kod ile daha çok iş
  • Statik nesne eşleştirme
  • Dinamik nesne eşleştirme
  • Stored Procedure desteği
  • Çoklu sorgu desteği
  • Toplu veri ekleme desteği
  • Kolaylıkla SQL sorgusu kullanımı
  • Kolaylıkla stored prodecure kullanımı

Ne Zaman Dapper Kullanılmalı?

Var olan yada yeni oluşturacağınız projede Dapper kullanıp kullanılmayacağı kararı, performans ele alınarak verilmelidir. Öyle ki Dapper’ın geliştiricileri Entity framework kullandıklarında Stackoverflow sitesinin trafiği ele alındığında yeteri kadar iyi olmadığını fark edip kendi Micro-ORM aracını geliştirdiler.

Ayrıca Dapper ADO.NET IDbConnection interface’ini kullanmaktadır. Bu sayede ADO.NET’in desteklediği herhangi bir veritabanı ile sorunsuz çalışabilmektedir.

Dapper Aslında Tam Olarak Ne Yapıyor?

ADO.NET kullanarak veritabanından veri almamızı sağlayan ve sonrasında Liste olarak kaydettiğimiz aşağıdaki kodu inceleyelim.

En basit düzeyde Dapper, 5.satır ile 21.satır arasındaki kodları aşağıdaki şekilde elde etmemizi sağlıyor.

products = connection.Query<Product>(sql);

Hadi o zaman gelin, yavaştan proje altyapısını oluşturalım ve konu anlatımına oradan devam edelim. DapperORM adında bir .Net Core 5 uygulaması oluşturalım ve katmanlarımızı, klasör yapımızı aşağıdaki gibi düzenleyelim.

Onion Architecture kullanarak oluşturduğumuz proje altyapısı
Onion Architecture kullanarak oluşturduğumuz proje altyapısı

Domain katmanına gelip entity sınıflarımızı oluşturmaya başlayabiliriz.

Entity Sınıfları

Entity sınıflarımızda DapperIgnore adında bir Attribute kullandık. Bunun sebebi generic dapper repository tasarlarken reflection ile elde edeceğimiz property listesinde, tablolar arası ilişki için kullandığımız property değerlerinin kullanılmayacak olması. Bu kısma generic repository yazarken tekrardan değineceğiz.

Application katmanına gelelim ve Interfaces klasörü altındaki gerekli dosyaları oluşturalım.

DapperContext adındaki sınıfımız bu IDapperContext interface’ini kullanarak bize generic repository tasarlarken temiz kod yazma imkanı verecek.

Validations klasörü altında Common adlı klasör oluşturalım ve ortak kurallar olmak üzere bakımı kolay, tekrar kullanılabilir bir yapı oluşturalım.

Genel Product Sınıfı Kuralları

Bu sınıfta Product nesnemize ait her bir property için extension metot oluşturduk. Bu sayede gerek silme, gerek güncelleme işlemlerinde kullanacağımız validation sınıflarında daha temiz bir kod altyapısı oluşturabileceğiz. Örnek kullanım açısından CreateProductValidator sınıfı aşağıdaki gibi görünmektedir.

Extension Metot kullanarak oluşturduğumuz Validator sınıfımız

Features adlı bir klasör oluşturalım ve burada CRUD işlemleri için Command ve Query sınıflarını MediatR kullanarak oluşturalım. CQRS kullanarak oluşturduğumuz handler ve request yapılarına uzaksanız buradaki yazımdan bilgi edinebilirsiniz.Örnek olarak CreateProductCommandHandler sınıfımız aşağıdaki gibi görünmektedir.

Request tipinde alacağımız nesneyi product sınıfına map ettikten sonra gerekli validate işlemlerini gerçekleştiriyoruz. Bir hata olması durumunda ErrorResult döndürüyor, işler tıkırında gittiğinde ise nesnemizi veritabanına ekliyor ve bununla ilgili bir mesaj içeren SuccessResult tipinde bir veri döndürüyoruz.

Application Katmanı Extension Metodu

Bu katmanda son olarak yukarıdaki gibi servisler arası bağlantımızı sağlayacak extension metot oluşturalım.

Artık yavaştan Persistence katmanına geçelim ve bizim için oldukça önemli olan dapper generic repository sınıfımızı tasarlayalım. Öncelikle repository sınıfımızda oldukça kullanacağımız DapperContext sınıfını, Context klasörü altında oluşturarak başlayalım.

Constructor içerisine IConfiguration nesnesi alıyoruz. Bu sayede GetConnection metodundan yeni bir SqlConnection bağlantısı oluşturabiliyoruz. Dapper tarafında oluşturacağımız her bir komut öncesi bağlantı açmamız gerektiği için Execute adında bir metot oluşturup parametre olarak oluşturduğumuz bağlantı nesnesini kullanan bir fonksiyon kabul ettiğini belirtiyoruz. Generic Repository sınıfını açıklarken bu dediğimi daha iyi anlayacaksınız.

  • 5.satırda constructor tarafında iki parametre alıyoruz. Bunlardan biri IoC tarafınca oluşturulacak IDapperContext instance, diğeri ise entity sınıflarının veritabanındaki tablo ismi.
  • 10.satırda GetColumns metodu, T olarak gönderilen Entity sınıfının Id kolonu ve DapperIgnore attribute’ü tarafından işaretlenmiş kolonların haricinde kalan property listesini elde etmemizi sağlıyor.
  • Add ve Update fonksiyonlarında gördüğünüz üzere GetColumns metodundan elde ettiğimiz her bir property, sql cümleciğimize parametre olarak ekleniyor.
  • Get ve GetAll fonksiyonlarında sql cümleciğini düzenleme sonrasında elde edilen değer geriye döndürülüyor. Burada DapperContext sınıfının Execute metodunu kullanmadık çünkü diğer fonksiyonların aksine burada geri dönüş değişkenimizin olması gerekmekte.

Product ve Category sınıflarımız için iki repository sınıfımızı da elde etmiş olduk. Bu katmanda son olarak aşağıdaki gibi servisler arası bağlantımızı sağlayacak extension metot oluşturalım ve artık API tarafına geçerek projemizi sonlandıralım.

API tarafında Startup.cs dosyasını açıyoruz ve aşağıdaki gibi düzenliyoruz.

API dökümantasyonunu oluşturacağımız Swagger için de çeşitli ayarlar yapmış bulunmaktayız. Swagger hakkında kendinizi eksik hissediyorsanız buradaki yazımdan bilgilenebilirsiniz. Extension metotlarımızı da kullandığımıza göre son olarak Controller tarafına geçelim ve yazımızı sonlandıralım.

Bu yazımda dapper nedir, özellikleri nedir ve nasıl kullanılır gibi soruların cevaplarını vermeye çalıştık.

Projeyi tam anlamıyla incelemek için github linkine buradan ulaşabilirsiniz.

Okuduğunuz için teşekkür ederim. Bir sonraki yazıda görüşmek dileğiyle.

--

--