Mert Özen Her Satırda Daha İleri
Backend .NET Core Web API — #11

DTO-entity dönüşümü: Elle yazmak mı, AutoMapper mı?

Mert Özen 8 Ağu 2026 12 dk 50 görüntülenme
DTO-entity dönüşümü: Elle yazmak mı, AutoMapper mı?

Entity ile DTO arasındaki dönüşümü konuşuyoruz. Elle mapping'in artıları, AutoMapper'ın ne zaman kolaylık ne zaman gizli maliyet olduğu ve projende hangisini seçmen gerektiğine dair pratik bir bakış.

Yedinci yazıda DTO'ları tanımış ve entity'yi doğrudan dönmenin neden kötü olduğunu konuşmuştuk. O yazıda entity'den DTO'ya dönüşümü elle, tek tek alan atayarak yapmıştık. İşe yarıyordu ama biraz yorucuydu. Bugün bu dönüşümü konu ediniyoruz: elle yazmaya devam mı etmeli, yoksa AutoMapper gibi bir araca mı geçmeli? Cevap sandığından biraz daha nüanslı.

Sorunu Hatırlayalım

Her endpoint'te aynı hikâye tekrar ediyor: veritabanından bir entity çekiyorsun, sonra onu dışarı dönmek için bir DTO'ya kopyalıyorsun. Ya da tam tersi: dışarıdan bir giriş DTO'su alıyorsun, onu veritabanına yazmak için bir entity'ye dönüştürüyorsun. Elle yapıldığında şuna benziyor:

var dto = new UserDto
{
    Id = user.Id,
    Name = user.Name,
    Email = user.Email
};

Üç alan için sorun yok. Ama entity'nde on beş alan varsa ve bu dönüşümü uygulamanın onlarca yerinde yapıyorsan, aynı sıkıcı atama kodunu tekrar tekrar yazıyorsun demektir. İşte AutoMapper tam bu tekrarı ortadan kaldırma vaadiyle geliyor.

AutoMapper Ne Vaat Ediyor?

AutoMapper, iki sınıf arasındaki dönüşümü senin için otomatik yapan bir kütüphane. Temel fikri şu: eğer entity'ndeki alan adlarıyla DTO'ndaki alan adları aynıysa, hangi alanın nereye gideceğini AutoMapper kendisi anlar. Sen tek tek atama yapmak yerine sadece "bunu şuna çevir" dersin.

Önce projene paketi ekliyorsun:

dotnet add package AutoMapper

Sonra hangi dönüşümlerin olacağını tanımlayan bir profil sınıfı yazıyorsun. Bu, AutoMapper'a "şu tipten şu tipe geçiş var" demenin yolu:

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap();
        CreateMap();
    }
}

Buradaki CreateMap<User, UserDto>(), "User'dan UserDto'ya dönüşüm mümkün" diyor. Alan adları eşleştiği sürece başka bir şey yazmana gerek yok; AutoMapper eşlemeyi kendi çözüyor. Artık servisinin içinde dönüşüm tek satıra iniyor:

var dto = _mapper.Map(user);

Üç satırlık atama koca bir Map çağrısına indi. On beş alanlı bir entity'de bu farkın ne kadar büyüdüğünü tahmin edebilirsin. İlk bakışta AutoMapper açık ara kazanıyor gibi görünüyor. Ama madalyonun bir de öbür yüzü var.

AutoMapper'ın Gizli Maliyeti

AutoMapper kod satırını azaltır, bu doğru. Ama bir şeyi de beraberinde getirir: sihir. Dönüşüm artık gözünün önünde, açık bir kod olarak durmaz; bir profilin ve kütüphanenin içinde, gizli kurallarla gerçekleşir. Küçük projelerde bu sorun değil. Ama işler karıştığında birkaç dezavantaj baş gösterir.

Birincisi, hata ayıklamanın zorlaşması. Bir alan beklenmedik şekilde boş geliyorsa, bunun sebebini elle yazılmış kodda anında görürsün; AutoMapper'da ise neyin nereye maplendiğini kütüphanenin davranışını bilerek çözmen gerekir. İkincisi, sessiz kırılmalar. Entity'ne yeni bir alan eklersin ama DTO'na eklemeyi unutursun; AutoMapper bunu çoğu zaman sessizce geçiştirir ve sen sorunu ancak çalışma zamanında fark edersin. Elle yazılan kodda böyle bir alan gözüne çarpardı.

Üçüncüsü ise okunabilirlik yanılsaması. AutoMapper kodu kısaltır ama her zaman anlaşılır kılmaz. Projeye yeni katılan biri, dönüşümün tam olarak ne yaptığını görmek için profil dosyasını açıp kütüphanenin kurallarını zihninde canlandırmak zorunda kalır. Oysa elle yazılmış bir atama, olduğu gibi, apaçık okunur.

Elle Mapping Aslında O Kadar Kötü mü?

Hayır, hatta çoğu zaman hiç fena değil. Elle yazılan dönüşümün en büyük erdemi şeffaflık: ne olduğunu tam olarak görürsün, sihir yoktur. Hangi alanın nereye gittiği kodun içinde apaçık durur, hata ayıklaması kolaydır ve yeni bir geliştirici tek bakışta anlar. Modern C#'ta bu kodu daha da toparlamanın yolları var; örneğin dönüşümü entity'ye bir metot olarak ekleyebilirsin:

public UserDto ToDto()
{
    return new UserDto
    {
        Id = this.Id,
        Name = this.Name,
        Email = this.Email
    };
}

Böylece dönüşüm mantığı tek bir yerde toplanır, çağırdığın yerde ise sadece user.ToDto() yazarsın. Hem AutoMapper'ın sağladığı toparlanmayı elde edersin, hem de sihirden uzak, şeffaf bir kod yazmış olursun. Bu yaklaşım, iki dünyanın iyi yanlarını birleştiren pratik bir orta yoldur.

Peki Hangisini Seçmeliyim?

Karar, projenin ölçeğine ve ekibin alışkanlığına bağlı. AutoMapper, entity'lerin büyük ve alan sayısının fazla olduğu, dönüşümlerin çok tekrar ettiği büyük projelerde ciddi zaman kazandırır. Ekibin bu araca alışkınsa, tutarlılık da başlı başına bir gerekçedir.

Ama küçük ve orta ölçekli bir projede, ya da öğrenme aşamasındaysan, elle mapping ile başlamanı öneririm. Neyin nereye gittiğini kendi gözünle görmek, dönüşüm mantığını çok daha sağlam oturtur. Sihirli bir araca güvenmeden önce, o aracın senin yerine ne yaptığını anlamak lazım. İhtiyaç gerçekten doğduğunda, yani tekrarlı kod seni yormaya başladığında AutoMapper'a geçersin. Baştan eklemek için acele etme.

Küçük Bir Deneme

Önce yedinci yazıdaki gibi entity'den DTO'ya dönüşümü elle yaz. Sonra aynı dönüşümü entity'ye eklediğin bir ToDto metoduna taşı ve çağırdığın yerde user.ToDto() kullan. Kodun çağrı tarafının nasıl sadeleştiğini gör. İstersen bir adım daha atıp AutoMapper'ı kurup aynı işi bir de onunla yap; üç yaklaşımı yan yana koyduğunda hangisinin senin için daha okunabilir olduğuna kendin karar verirsin. Bu karşılaştırma, "hangisi daha iyi?" sorusunu senin projen bağlamında cevaplar.

Bir sonraki yazıda dependency injection'ı derinlemesine ele alacağız: servisleri kaydederken kullandığımız lifetime'ları (singleton, scoped, transient) ve bunların neden bu kadar önemli olduğunu konuşacağız. Şimdiye kadar oluşturduğumuz servisler, o kavramları somutlaştırmak için tam da ihtiyacımız olan örnekler.