Çoğu yazılım uygulamasının belli mimari kurallar çerçevisinde farklı katmanlara ayrılarak geliştirilmesi beklenir ve buna n-tier architecture denir. N-tier architecture presentation tier, middle tier yada data tier gibi çeşitli katmanlardan oluşabilir. Presentation katmanında uygulamanızın UI tarafını ilgilendiren arayüzler bulunur, Middle katmanda business logic'i ilgilendiren geliştirmeler yapılır ve aynı zamanda database ile etkileşimde bu katmanda bulunur. Data katmanı ise uygulamanızdaki SQL Server, Oracle gibi database context'lerini içeren katmandır. Bu katman belkide uygulamadaki en önemli katmandır sebebi ise database. Data bizim için en önemli şey ve database'ler ile olan veri alış verişi işin en güvenlikli ve generic olması gereken yerlerin başında gelir.
Database varsa CRUD işlemi (Create, Read, Update, Delete) heralde olmazsa olmazdır ve data katmanı ile doğrudan business logic'in bulunduğu middle katman haberleşsin istenilmez ve bu durum bazen uygulamanızın büyüklüğüne göre çeşitli sorunlarda çıkartabilir. Repository pattern bu ihtiyacı karşılayan pattern olarak karşımıza çıkıyor ve temelde yaptığı iş ise business logic ile data access arasında arabulucu görevi görme.
Repository Pattern Faydaları
- Maintainability (sonradan bakım kolaylılığı) arttırır,
- Unit-test yapabilmemizi kolaylaştırır,
- Esnek bir mimari uygulamamızı sağlar,
- Yeni gelecek modüller veya istenilen değişiklikleri kolayca entegre edebilmeyi sağlar,
- Domain driven development'ın önünü açar.
Repository Pattern Uygulaması
Şimdi örnek bir proje üzerinden Repository Pattern nasıl uygulanır görelim. Projeyi geliştirirken projenizde EntityFramework kurulu ve SampleDbContext adında bir database context'inizin olduğunu varsayarak ilerliyor olacağız.
1.Adım - IRepository adında CRUD işlemleri yapabilmemizi sağlayacak Generic bir interface metodlarını tanımlama.
public interface IRepository<T> where T : class
{
IEnumerable<t> SelectAll();
T SelectByID(object id);
void Insert(T obj);
void Update(T obj);
void Delete(object id);
void Save();
}
2.Adım - BaseRepository adında Generic IRepository interface'inden implement olan class'ı oluşturma.
public abstract class BaseRepository<T> : IRepository<T> where T : class
{
private SampleDbContext db = null;
private DbSet<t> table = null;
public BaseRepository()
{
this.db = new SampleDbContext();
table = db.Set<T>();
}
public BaseRepository(SampleDbContext db)
{
this.db = db;
table = db.Set<T>();
}
public IEnumerable<T> SelectAll()
{
return table.ToList();
}
public T SelectByID(object id)
{
return table.Find(id);
}
public void Insert(T obj)
{
table.Add(obj);
}
public void Update(T obj)
{
table.Attach(obj);
db.Entry(obj).State = EntityState.Modified;
}
public void Delete(object id)
{
T existing = table.Find(id);
table.Remove(existing);
}
public void Save()
{
db.SaveChanges();
}
}
3.Adım - Employee adında örnek bir Entity tanımlama
public class Employee
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
4.Adım - BaseRepository den inherit olan Employee entity si için EmployeeRepository class'ını tanımlama
public class EmployeeRepository : BaseRepository<Employee>
{
}
5.Adım - Yazmış olduğumuz EmployeeRepository'yi kullanmak
void Main(string[] args)
{
var empRepository = new EmployeeRepository();
empRepository.SelectAll();
}
Projemiz hazır. Bundan sonra tanımlayacağınız entity'ler için EmployeeRepository de olduğu gibi Generic olarak yazmış olduğumuz BaseRepository'den türeyen Repository'ler tanımlayarak projeyi geliştirmeye devam edebiliriz.
Not : Bir rivayete göre Repository Design Pattern, Design Pattern ailesi içerisinde en çok kullanılan pattern olduğu söylenir.