Not içeriği yükleniyor...
// Markdown dosyası okunuyor
// İçerik işleniyor
// Syntax highlighting hazırlanıyor
// Markdown dosyası okunuyor
// İçerik işleniyor
// Syntax highlighting hazırlanıyor
Repository pattern implementation, data access layer abstraction ve domain-infrastructure separation. CQRS pattern ile entegrasyon.
Order
gibi Aggregate’leri ve onun sınırları içindeki Entity ve Value Object’leri nasıl modelleyeceğimizi öğrendik. Peki, bu Aggregate’leri nasıl oluşturacak, güncelleyecek ve kalıcı hale getireceğiz?
İşte burada Domain-Driven Design’ın bir diğer yapı taşı devreye giriyor: Repository.
Repository, Aggregate’lerimizi kalıcı depolama (ör. veritabanı) ile etkileşime sokan ve bunu domain kodundan soyutlayan katmandır. Şimdi Repository’nin ne olduğunu ve neden önemli olduğunu inceleyelim.Amaç | Açıklama |
---|---|
Persistence'ı soyutlamak | Domain katmanı, EF Core, Mongo, SQL gibi veri katmanından haberdar olmaz |
Aggregate Root’a tek kapı sunmak | Aggregate’leri hep Root seviyesinden yükleyip kaydederiz |
Kolay test ve bakım | Veritabanı olmadan domain kodunu test edebiliriz |
Order
Aggregate için bir Repository şöyle başlar:
bashpublic interface IOrderRepository { Task<Order> GetByIdAsync(Guid id); Task AddAsync(Order order); Task UpdateAsync(Order order); Task DeleteAsync(Order order); }
bashpublic class OrderRepository : IOrderRepository { private readonly AppDbContext _context; public OrderRepository(AppDbContext context) { _context = context; } public async Task<Order> GetByIdAsync(Guid id) { return await _context.Orders .Include(o => o.Items) .FirstOrDefaultAsync(o => o.Id == id); } public async Task AddAsync(Order order) { await _context.Orders.AddAsync(order); } public async Task UpdateAsync(Order order) { _context.Orders.Update(order); } public async Task DeleteAsync(Order order) { _context.Orders.Remove(order); } }
OrderRepository
, UserRepository
, ProductRepository
gibi repository'ler hep Aggregate Root'lar için yazılır.SaveChanges
çağrısıyla kalıcı hale getirir.
DDD'de şöyle düşün:
“Bir Use Case (örnek: Sipariş Oluşturma) = Bir Transaction = Bir Unit of Work”Yarar | Açıklama |
---|---|
Tüm işlemleri tek noktadan commit etme | 1 kez SaveChanges çağırırsın |
Transaction bütünlüğü sağlar | Tüm işlemler ya birlikte olur, ya hiçbiri olmaz |
Test edilebilirlik | Tek noktadan sahte (fake/mock) kontrol yapılabilir |
Repository’leri koordine eder | Birden fazla Aggregate veya Repository ile çalışıldığında işlem sırası, save süreci kontrol altındadır |
IUnitOfWork
Arayüzübashpublic interface IUnitOfWork { Task<int> SaveChangesAsync(CancellationToken cancellationToken = default); }
bashpublic class EfUnitOfWork : IUnitOfWork { private readonly AppDbContext _context; public EfUnitOfWork(AppDbContext context) { _context = context; } public async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) { return await _context.SaveChangesAsync(cancellationToken); } }
bashpublic class OrderService { private readonly IOrderRepository _orderRepository; private readonly IUnitOfWork _unitOfWork; public OrderService(IOrderRepository orderRepository, IUnitOfWork unitOfWork) { _orderRepository = orderRepository; _unitOfWork = unitOfWork; } public async Task CreateOrderAsync(CreateOrderDto dto) { var order = new Order(...); order.AddItem(...); await _orderRepository.AddAsync(order); await _unitOfWork.SaveChangesAsync(); // Tüm değişiklikler burada commit edilir } }