Genel veri havuzuyum, ancak genel veri havuzu kalıplarından uzaklaştım. Bunun yerine depolarımı hizmet ettikleri iş işleviyle hizalıyorum. Depolar ORM'i soyutlamayı amaçlamamaktadır, çünkü bu değiştirmeyi beklediğim bir şey değildir ve aynı zamanda bir havuzu çok ayrıntılı yapmaktan kaçınırım. (Yani CRUD) Depolarım iki ila üç temel amaca hizmet ediyor:
- Veri alma
- Veri oluşturma
- Zor silme
Veri alımı için, havuz her zaman geri döner IQueryable<TEntity>
. Veri oluşturmak için TEntity döndürür. Havuz, yumuşak silme kalıpları kullanan sistemler için yetkilendirme "etkin" durumu ve geçmiş verileri kullanan sistemler için "geçerli" durumu gibi temel düzey filtrelerimi işler. Veri oluşturma sadece gerekli referansların çözülmesini ve ilişkilendirilmesini ve varlığın kurulmuş ve kullanıma hazır olmasını sağlamaktan sorumludur.
Veri güncelleme, söz konusu varlıklar ile çalışan iş mantığının sorumluluğundadır. Bu, doğrulama kuralları gibi şeyleri içerebilir. Bunu depo yöntemiyle kapsüllemeye çalışmıyorum.
Sistemlerimin çoğundaki silme işlemi yumuşak silinir, bu nedenle veri güncellemesi altına girer. (IsActive = false) Sıkı silmeler durumunda bu, Depodaki tek satırlık olacaktır.
Neden depolar? Test-yeteneği. Elbette, DbContext alay edilebilir, ancak dönen bir sınıfı alay etmek daha kolaydırIQueryable<TEntity>
. Ayrıca UoW deseni ile de güzel oynuyorlar, şahsen Mehdime'in DbContextScope modelini istediğim seviyede (MVC'deki Kontrolörler) kapsamak için kullanıyorum ve denetleyicilerim ve yardımcı servis sınıflarımın referansları geçmesine gerek kalmadan depoları kullanmasına izin veriyorum etrafında UoW / dbContext. IQueryable kullanmak, depoda çok fazla sarma yöntemine ihtiyacınız olmadığı anlamına gelir ve kodunuz verilerin nasıl kullanılacağını optimize edebilir. Örneğin, deponun "Var" veya "Say" gibi yöntemleri göstermesi veya alt veri kümeleri istediğiniz durumlarda varlıkları diğer POCO'larla sarmaya çalışması gerekmez. İhtiyaç duyabileceğiniz veya ihtiyaç duymayabileceğiniz ilgili veriler için istekli yükleme seçeneklerini kullanmaları bile gerekmez. IQueryable'ı geçerek, çağrı kodu şunları yapabilir:
.Any()
.Count()
.Include() // Generally avoided, instead I use .Select()
.Where()
.Select(x => new ViewModel or Anon. Type)
.Skip().Take()
.FirstOrDefault() / .SingleOrDefault() / .ToList()
Çok esnek ve test edilmiş bir PoV'dan alaycı depomun yalnızca doldurulmuş varlık nesneleri listelerini döndürmesi gerekiyor.
Genel depolara gelince, çoğu zaman bunlardan uzaklaştım çünkü tablo başına bir havuz bulduğunuzda, denetleyicileriniz / hizmetleriniz bir iş eylemi yapmak için birkaç havuza referanslarla sonuçlanır. Çoğu durumda, bu depolardan yalnızca bir veya iki tanesi gerçekten yazma işlemleri yapıyor (navigasyon özelliklerini düzgün kullanmanız şartıyla), geri kalanı Okumaları destekliyorsa. 5 veya 6 farklı depoya çarpmak yerine, bir sipariş oluştururken referans için ilgili siparişleri okuyabilen ve ilgili aramaları (hafif müşteri nesneleri, ürünler, vb.) Okuyabilen OrdersRepository gibi bir şey olmasını tercih ederim. DNRY saflarını ihlal edebilir, ancak bununla ilgili iddiam, deponun amacının ilgili referansları içeren Emirlerin yaratılmasına hizmet etmektir.Repository<Product>
sipariş bazında sadece birkaç avuç dolusu alana sahip bir işletmeye ihtiyacım olduğu ürünleri almak için. Benim OrderRepository, daha iyi denemek ve uygulama ihtiyaçlarının farklı alanlarına hizmet ve / veya bazı karmaşık geçiş filtreleme ifadesi hizmet için birkaç "Get" yöntemleri olan bir daha güzel bulmak .GetProducts()
dönen bir yöntem olabilir .IQueryable<ProductSummary>
Repository<Product>
Takip etmesi, test etmesi ve ayarlaması kolay basit kodları tercih ederim. Kötü şekillerde istismar edilebilir, ancak kötüye kullanımın tespit edilmesi ve düzeltilmesi kolay olan bir şeyi, kodu kötüye kullanılamayacak, başarısız olamayacak ve " müşterinin sonunda yapması için ödediği şeyi yapmak için bir kabus. :)