Örneğin repository pattern için:

Interface

public interface IDinnerRepository 
{
    IQueryable<Dinner> FindAllDinners();
    IQueryable<Dinner> FindDinnersByText(string q);

    Dinner GetDinner(int id);

    void Add(Dinner dinner);
    void Delete(Dinner dinner);

    void Save();
}

Interface i implement eden sınıf

public class DinnerRepository : NerdDinner.Models.IDinnerRepository
{
    NerdDinnerEntities db = new NerdDinnerEntities();

    Public IQueryable<Dinner> FindDinnersByText(string q)
    {
          return db.Dinners.Where(d => d.Title.Contains(q)
                 || d.Description.Contains(q)
                 || d.HostedBy.Contains(q));
    }

    public IQueryable<Dinner> FindAllDinners()
    {
          return db.Dinners;
    }

    public Dinner GetDinner(int id)
    {
         return db.Dinners.SingleOrDefault(d => d.DinnerID == id);
    }

    public void Add(Dinner dinner)
    {
         db.Dinners.AddObject(dinner);
    }

    public void Delete(Dinner dinner)
    {
        foreach (RSVP rsvp in dinner.RSVPs.ToList())
            db.RSVPs.DeleteObject(rsvp);

        db.Dinners.DeleteObject(dinner);
   }

   public void Save()
   {
        db.SaveChanges();
   }
}

Normalde yukardaki sınıfı kullanmak için nesnesini oluşturup, içerisindeki fonksiyonları kullanabiliriz şöyleki

public class DinnerOperation
{
    DinnerRepository dr = new DinnerRepository();

    // insert işlemi
    public void InsertDinner()
    {
        Dinner dinner = dr.GetDinner(5);
        dr.Dinner.Add(dinner);
        dr.Save();
    }

    // delete işlemi
    public void DeleteDinner()
    {
        Dinner dinner = dr.GetDinner(5);
        dr.Dinner.Delete(dinner);
        dr.Save();
    }
}

bu işlemi zaten entityFramework ile de yapabiliyorum :

public class DinnerOperation
{
    DinnerEntities entity = new DinnerEntities();

    // insert işlemi
    public void InsertDinner()
    {
        Dinner dinner = entity.Dinners.Find(5);
        entity.Dinner.Add(dinner);
        entity.SaveChanges();
    }

    // delete işlemi
    public void DeleteDinner()
    {
        Dinner dinner = entity.Dinners.Find(5);
        entity.Dinner.Remove(dinner);
        entity.SaveChanges();
    }
}

Repository tasarım desenini entityFramework ile bu şekilde kullanınca anlamı kalmıyor, ya da ben tamamen yanlış anlamışım. Zaten entityFramework de bu patternları kullandıgı için bunları saglıyor.

Soru : EntityFramework (NHibernate, ve ya daha farklı framework ler) kullanırken tasarım desenleri ne zaman işimize yarayacak? Framework lerin zaten kullanmış olmaları yeterli değil mi?

soruldu: 21 Oca '13, 08:40

AliR%C4%B1za%20Ad%C4%B1yah%C5%9Fi's gravatar image

AliRıza Adıyahşi ♦
7.9k146288
cevap kabul oranı: 44%

değiştirildi: 22 Nis '13, 08:31


EntityFramework hakkinda bilgim yok, ama NHibernate kelimesi gecinde, Hibernate ve ORM ile iliskilendirdim. Bu konudaki düsüncem söyle.

Veri katmanini alt ve üst veri katmani olmak üzere iki ya da daha fazla katmandan olusuyor seklinde düsünmekte fayda var. Bir JPA implementasyonu kullanirken (örnegin Hibernate) entityManager.find(), entityManager.select() gibi islemler yapabiliyorum. Lakin bunlar tamamen JPA API'sine has olan metot kullanimlari. Eger bu metotlari dogrudan repository olmadan üst katmanlarin kullanimina sunarsam, üst katmanlar ile JPA arasinda bir bagimlilik olusur. JPA bünyesinde meydana gelen her degisiklik üst katmanlari dogrudan etkiler ve uygulamanin tümünü daha kirilgan hale getirir. JPA implementasyonunu gizlemek amaciyla JPA ile üst katmanlar arasina bir Repository implemenetasyonu yerlestirilebilir. Repository tüm JPA detaylarini tanir, ama bunlari üst katmanlara göstermez. Sundugu find*() metotlari ile üst katmanlarin gereksinimlerini tatmin eder. Böylece uygulamayi büyük capta etkilemeden ORM implementasyonu degistirilebilir. Bunun icin yeni bir Repository implemenetasyonu yeterli olacaktir.

Repository interface ve implementasyonu burada üst veri katmanini olustururken, JPA implementasyonunun kullanimi alt veri katmanini olusturmaktadir.

permanent link

cevaplandı: 22 Nis '13, 09:55

%C3%B6zcanacar's gravatar image

özcanacar ♦♦
17.2k59183183
cevap kabul oranı: 52%

Hocam codeproject sitesinde okudugum bir makalede de sizinkine yakın bir, anlatım vardı, yani her ne kadar ORM araçları Repository kullansada bu tam bir soyutlama olmuyor diyordu. Sizde oyle diyorsunuz. Tamam bunu anladım. Diger cevabın altındaki en son yorum hakkında ne dusunuyorsunuz. Mesela siz demişsiniz Find, Select metodları, bu metodlar butun sınıflar için ortak olabilir ama, sınıfa özel metodlar için ne yapabiliriz, bunlar iş katmanının mı görevi. Yani repository kullanan sınıfların mı görevi olmalı. Çünkü generic bir repository yazmak için sınıfa özel işler olmamalı.

(22 Nis '13, 10:10) AliRıza Adıyahşi ♦ AliR%C4%B1za%20Ad%C4%B1yah%C5%9Fi's gravatar image
1

Servis katmaninin her zaman spesifik ihtiyaclari oldugu icin jenerik repositorilerin kullanimi pek kolay degil. Bu yüzden repository siniflari servis katmaninin ihtiyaclarini karsilayacak sekilde yapilandirilmali. Örnegin servis katmanindaki bir sinifta addRole(role) isminde bir metot varsa, bu veri katmanindaki RoleRepository.addRole(role) metodunu kullanarak veri katmaninda istedigi hizmeti alir. RoleRepository.addRole() metodu da bünyesinde entityManager.save(role) seklinde dogrudan ORM aracini kullanarak gerekli veri tabani islemini yapar.

(22 Nis '13, 10:26) özcanacar ♦♦ %C3%B6zcanacar's gravatar image

Merhaba,

Entity Framework ile çalışırken tartışılan ve hala da tartışılmaya devam edilen konulardan bir tanesi, Repository ve UnitOfWork patternleridir.

Bir kısım; DbContext sınıfının UnitOfWork, DbSet sınıfının ise Repository implementasyonu olduğunu ve dolayısı ile Entity Framework ile bu patternları kullanmasının karmaşaya yol açacağını savunmaktadır.

Bir kısım ise; Repository ve UnitOfWork patternlarının veri erişim amaçlı patternlar olduğunu ve veri erişim teknolojilerini soyutlayacak şekilde implemente edilmesi gerektiğini savunur (ben de bu grubun içerisindeyim :))

Buradaki implementasyonu aşağıdaki gibi biraz daha genişletirsek

public interface IRepository<T>
{
    IQueryable<T> FindAll();
    IQueryable<T> FindByText(string q);

    T Get(int id);

    void Add(T entity);
    void Delete(T entity);

    void Save();
}

elimizde generic bir IRepository interface'i oluşmuş olur. Bu interface'i yukarıdakine benzer bir şekilde Entity Framework ile genişlettiğimizi düşünelim.

public class Repository<T> : IRepository<T>
{
    //entity framework ile implement edildi
}

IRepository interface'i üzerinden kendi repositorylerimizi yine interface olarak üretebiliriz.

public interface IDinnerRepository : IRepository<Dinner>
{
    bool IsReservedForTonight(int dinnerID);
    bool GetRestaurantName(int dinnerId);
}

Böylelikle elimizde sadece dinner ile alakalı methodları yazacağımız ve aynı zamanda tüm entityler için ortak olan temel veri işlemlerini sağlayabileceğimiz bir interface'imiz olmuş oldu.

Bundan sonra yapacağımız tüm repository'ler ise şu şekilde olabilir.

public class DinnerRepository : Repository<T>, IDinnerRepository
{
    //dinner'a özel yazdığımız iki method implementasyonu
}

Sizin yazmış olduğunuz DinnerOperation sınıfı, herhangi bir interface'i implemente etmediği için bu sınıfı kullanan tüm yapılar hem bu sınıfa, hem Entity Framework'e, dolayısıyla hem de veritabanına bağımlı olacaklardır.

Bizim genişlettiğimiz yapıda ise tüm repository sınıfları mutlaka bir interface'i implemente etmektedir. Dolayısı ile ne Entity Framework'e, ne de veritabanına direkt bağımlılık taşımamaktadır.

Repository pattern, altındaki tüm veri erişim teknolojilerini soyutlama amaçlı kullanılmakta ve dolayısı ile uygulamanızı hem esnek, hem de test edilebilir bir yapıda geliştirmenize yardımcı olmaktadır.

ORM teknolojilerinin sağlamış olduğu bazı faydaları ise, yapmış olduğunuz implementasyondan dolayı kaybedebilirsiniz. (Örneğin; change tracking, lazy loading)

Dolayısı ile repository pattern'i kullanırken bu ihtiyaçlarınızı da değerlendirmenizi tavsiye ederim.

permanent link

cevaplandı: 12 Mar '13, 08:05

tilikoglu's gravatar image

tilikoglu
8602816
cevap kabul oranı: 18%

değiştirildi: 12 Mar '13, 08:06

Cevabınız için teşekkürler. Aslında bu soruya her cevap aldığımda yine kafam karışıyor, bunun sebebide sizin dediğiniz gibi hala tartışılıyor olması. Bu arada DinnerOperation aslında programı temsil ediyor. yani bu sınıfı herhangibir yerde kullanmayacağım zaten. MVC de controller sınıfları içerisinde işlemler gerçekleştiğinden direk oyle yazdım. Ama ne dediğinizi anladım sayılır. Burada sormuştum, çok farklı cevaplar geldi ve hepside mantıklı :)

(12 Mar '13, 08:31) AliRıza Adıyahşi ♦ AliR%C4%B1za%20Ad%C4%B1yah%C5%9Fi's gravatar image

Ben şu an direk kullanmayı tercih ediyorum. Çünkü repository pattern yazdım ve kullanmak isteyince baktım başa dönüyor. Başa dönüyor derken, aslında entityFramework fonksiyonları bir daha farklı fonksiyonlara döndürmüş oluyorum. Yani sonuç olarak yine entityFramework fonksiyonları çıkıyor ortaya. Bu patternların iki avantajı var. UnitTest ve koların tekrar kullanımı. Ama entity Unit Testi zaten destekliyor. Kod esnekliğini sağlayacak kadar da büyük proje daha yapmadım :) Bende şu an diğer grup içerisindeyim :)

(12 Mar '13, 08:36) AliRıza Adıyahşi ♦ AliR%C4%B1za%20Ad%C4%B1yah%C5%9Fi's gravatar image

DinnerOperation ile ilgili kısmı yanlış anlamışım, kusura bakmayın. Verdiğiniz linkteki 2. cevaba yakın bir cevap vermişim ben de :) Bu cevabın altında yorumlarda da oldukça önemli bir tartışma var, IQueryable ve LINQ ile ilgili, onları da dikkate almanızı tavsiye ederim. Kolay gelsin, başarılar

(12 Mar '13, 09:15) tilikoglu tilikoglu's gravatar image

Hocam, generic repository için, genel anlamlı metodlar var (Add, Delete, Insert). Bunlar dısında mesela Role sınıfı oldugunu düşünelim. Role ile alakalı; AddUserToRole, UserIsInRole, ... gibi, sadece belli sınıfa özel metodlar olsun. Bu metodları generic repository içerisinde tanımlayamayız. Genel anlamdaki bütün metodlar da, zaten ORM araçlarında var. Sınıfa özel bu metodlar için sizin düşünceniz nedir. Bunlar DataAccess değil de, Business kısmını mı ilgilendiren bir konu?

(22 Nis '13, 08:25) AliRıza Adıyahşi ♦ AliR%C4%B1za%20Ad%C4%B1yah%C5%9Fi's gravatar image
1

yukarıdaki cevapta IDinnerRepository ve DinnerRepository için yazdığım örnekler, bu sınıfa ait spesifik methodların nereye yazılabileceği ile ilgili idi. Her bir repository, generic repository'den miras alabilmeli, ancak spesifik methodları kendi üzerinde barındırmalıdır diye düşünüyorum.

(23 Nis '13, 07:22) tilikoglu tilikoglu's gravatar image
Cevabınız
toggle preview

Bu soruyu takip et

E-Posta üzerinden:

Üyelik girişi yaptıktan sonra abonelik işlemlerini yapabilirsiniz

RSS üzerinden:

Cevaplar

Cevaplar ve Yorumlar

Yazı Formatlama

  • *italic* ya da _italic_
  • **bold** ya da __bold__
  • link:[text](http://url.com/ "başlık")
  • resim?![alt text](/path/img.jpg "başlık")
  • liste: 1. Foo 2. Bar
  • temel HTML etiketleri de kullanılabilir

Bu sorunun etiketleri:

×1,079
×238
×5

Soruldu: 21 Oca '13, 08:40

Görüntüleme: 1,549 kez

Son güncelleme: 23 Nis '13, 07:22

powered by BitNami OSQA