Depo Kalıbı - DAL


92

Aynı şey mi? Rob Connery'nin Storefront eğitimini izlemeyi yeni bitirdim ve benzer teknikler gibi görünüyorlar. Yani, bir DAL nesnesini gerçekleştirdiğimde GetStuff, Add / Delete vb. Yöntemlere sahibim ve her zaman arayüzü önce yazıyorum, böylece db'yi daha sonra değiştirebilirim.

Kafamı karıştırıyor muyum?

Yanıtlar:


88

İşleri karıştıran kesinlikle sen değilsin. :-)

Sanırım sorunun cevabı ne kadar saf olmak istediğinize bağlı.

Katı bir DDD bakış açısı istiyorsanız, bu sizi bir yola götürecektir. Depoya, hizmetler ve veritabanı arasında ayrılan katmanın arayüzünü standartlaştırmamıza yardımcı olan bir model olarak bakarsanız, sizi başka bir yere götürecektir.

Benim bakış açıma göre veri havuzu, verilere erişim için açıkça belirlenmiş bir katman veya başka bir deyişle Veri Erişim Katmanınızı uygulamanın standartlaştırılmış bir yoludur. Farklı depo uygulamaları arasında bazı farklılıklar vardır, ancak konsept aynıdır.

Bazı kişiler depoya daha fazla DDD kısıtlaması koyarken, diğerleri depoyu veritabanı ile hizmet katmanı arasında uygun bir aracı olarak kullanacaktır. DAL gibi bir havuz, hizmet katmanını veri erişim özelliklerinden ayırır.

Bunları farklı kılan bir uygulama sorunu, bir havuzun genellikle bir spesifikasyon alan yöntemlerle oluşturulmasıdır. Depo, bu spesifikasyonu karşılayan verileri döndürecektir. Gördüğüm çoğu geleneksel DAL, yöntemin herhangi bir sayıda parametre alacağı daha büyük bir yöntem setine sahip olacaktır. Bu küçük bir fark gibi görünse de, Linq ve İfadeler alemlerine girdiğinizde büyük bir sorun. Varsayılan depo arayüzümüz şuna benzer:

public interface IRepository : IDisposable
{
    T[] GetAll<T>();
    T[] GetAll<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter, List<Expression<Func<T, object>>> subSelectors);
    void Delete<T>(T entity);
    void Add<T>(T entity);
    int SaveChanges();
    DbTransaction BeginTransaction();
}

Bu bir DAL mı yoksa bir depo mu? Bu durumda her ikisi de sanırım.

Kim


5
Partiye burada geç kaldınız, ancak neden T [], List <T> (veya benzeri) değil?
Mike Kingscott

27
Belki IEnumerable <T> en iyisidir.
Venemo

9
veya IQueryable <T>
kenwarner

1
Bence IQueryable <T> en iyi seçim olacaktır, çünkü yöntemleri zincirlemenize ve veritabanının tüm işi yapmasına izin vererek yürütmeyi ertelemenize izin verir.
0lukasz0

4
@kenwarner IQueryable <T> 'yi döndürmenin soyutlamayı sızdırdığını düşünüyorum. Deponuzdan etki alanı nesnelerini iade etmelisiniz.
Matthew

42

Veri havuzu, birçok farklı şekilde uygulanabilen bir modeldir, ancak veri erişim katmanının çok açık bir sorumluluğu vardır: DAL, CRUD işlemlerini gerçekleştirmek için veri depolamanıza nasıl bağlanacağını bilmelidir.

Bir depo edebilir bir DAL olmak, ama aynı zamanda DAL önünde oturmak ve iş nesnesi katmanı ve veri katmanı arasında bir köprü görevi görebilir. Hangi uygulamanın kullanılacağı projeden projeye farklılık gösterecektir.


23

Büyük bir fark, DAO'nun alanınızdaki herhangi bir varlık için kalıcılıkla başa çıkmanın genel bir yolu olmasıdır. Öte yandan bir depo yalnızca toplu köklerle ilgilenir.


26
Anlaşılması gereken ilk şey, bir model olarak bir havuzun Etki Alanı Odaklı Tasarım olarak bilinen daha büyük sistemin bir parçası olduğudur. DDD etki alanında nesneler, her biri bir toplu köke sahip olan kümeler halinde gruplanır. Örneğin, PurchaseOrder bir toplu köktür ve Sipariş Öğeleri, toplu kök içindeki alt öğelerdir. Bir depo yalnızca toplu köklerle ilgilenir. Yani, örneğin bir OrderItem hiçbir zaman toplu kökünden bağımsız olarak yüklenmez. Dolayısıyla, DDD'de asla bir OrderItem deponuz olmazdı. Ancak, DDD olmayan bir sistemde, Dao kökleri toplamakla sınırlı olmadığından bir OrderItem Dao'ya sahip olabilirsiniz.
düşünceli

NG, Teşekkürler! Ben de öyle görmeye başlamıştım ama bu onu netleştiriyor. Tüm DDD literatürünü okumaya başlamam gerekecek!
David

@bingle, toplu köklerin ve alt nesnelerin bir depo tarafından nasıl yüklendiğinin harika bir açıklaması. Çok katmanlı bir uygulamada bir depo nerede bulunur? Bir veri erişim katmanı kitaplığında olduğunu görebiliyordum, ancak alt nesneleri yüklediği için bunun yerine mantık katmanı kitaplığında mı var olmalı? İçimden gelen bilgiler bana veri erişim katmanını söylüyor, ancak konuyla ilgili fikrinizi istedim.
Jeff LaFay

12

Benzer bir soruya bir cevap arıyordum ve en yüksek dereceli iki cevaba katılıyordum. Kendim için aydınlatmaya çalışmak, ben buldum eğer Depo desenli el-ele gitmek Özellikleri, etki alanı modelinin birinci sınıf üyeleri olarak uygulanmaktadır, o zaman can

  • Spesifikasyon tanımlarını farklı parametrelerle yeniden kullanma ,
  • işlemek , Şartname örneklerini parametreleri (örneğin uzmanlaşmak) mevcut
  • onları birleştir
  • herhangi bir veri tabanına erişim yapmak zorunda kalmadan bunlar üzerinde iş mantığı gerçekleştirmek ,
  • ve tabii ki onları gerçek Depo uygulamalarından bağımsız olarak birim test edin.

Hatta şimdiye kadar incelenmiş olup gidebilir sürece "Veri Havuzu" deposu desen Şartname deseni ile birlikte kullanılır, gerçekten değil ama bir DAL. Sözde kodda uydurma bir örnek:

specification100 = new AccountHasMoreOrdersThan(100)
specification200 = new AccountHasMoreOrdersThan(200)

assert that specification200.isSpecialCaseOf(specification100)

specificationAge = new AccountIsOlderThan('2000-01-01')

combinedSpec = new CompositeSpecification(
    SpecificationOperator.And, specification200, specificationAge)

for each account in Repository<Account>.GetAllSatisfying(combinedSpec)
    assert that account.Created < '2000-01-01'
    assert that account.Orders.Count > 200

Ayrıntılar için Fowler'in Spesifikasyon Denemesi'ne bakın (yukarıdakilere dayandırdığım şey bu).

Bir DAL aşağıdaki gibi özel yöntemlere sahip olacaktır:

IoCManager.InstanceFor<IAccountDAO>()
    .GetAccountsWithAtLeastOrdersAndCreatedBefore(200, '2000-01-01')

Eğer bu yaklaşımla DAL / DAO arayüzleri her tanımlamak zorunda, özellikle de bu hızla hantal olabilir nasıl görebilirsiniz ve DAL sorgu yöntemini uygulamak.

.NET'te LINQ sorguları , spesifikasyonları uygulamanın bir yolu olabilir , ancak Spesifikasyonu (ifadeleri) birleştirmek, evde yetiştirilen bir çözümle olduğu kadar sorunsuz olmayabilir. Bunun için bazı fikirler bu GK Sorusunda açıklanmıştır .


2

Kişisel görüşüm, her şeyin haritalama ile ilgili olduğu yönünde, bkz: http://www.martinfowler.com/eaaCatalog/repository.html . Dolayısıyla, havuzdan gelen çıktı / girdi, DAL üzerinde herhangi bir şey olabilen etki alanı nesneleridir. Benim için bu önemli bir ekleme / kısıtlamadır, çünkü bir veritabanı / hizmet / her ne olursa olsun farklı bir düzende bir depo uygulaması ekleyebilir ve haritalama yapmaya konsantre olmak için net bir yeriniz vardır. Bu kısıtlamayı kullanmayacaksanız ve eşleştirmeyi başka bir yerde yapacaksanız, verileri temsil etmenin farklı yollarına sahip olmak, kodu değiştirmemesi gereken yerlerde etkileyebilir.


1

Her şey yorumlama ve bağlamla ilgili. Çok benzer veya gerçekten çok farklı olabilirler, ancak çözüm işi yaptığı sürece, bir isimde ne var!


1

Dış dünyada (yani müşteri kodu) deposu, aşağıdakiler dışında DAL ile aynıdır:

(1) ekleme / güncelleme / silme yöntemleri, parametre olarak veri taşıyıcı nesnesine sahip olmakla sınırlıdır.

(2) okuma işlemi için bir DAL (örneğin GetByPK) veya gelişmiş spesifikasyon gibi basit spesifikasyonlar alabilir.

Dahili olarak, gerçek CRUD işlemini gerçekleştirmek için bir Veri Eşleyici Katmanı (örneğin, varlık çerçevesi içeriği vb.) İle çalışır.

Depo modeli ne anlama gelmez: -

Ayrıca, ekleme / güncelleme / silme yöntemleriyle gerçekleştirilen tüm bellek içi değişiklikleri veritabanına işleyen Ekle / Güncelle / Sil yöntemlerinin yanı sıra, depo modeli örnek uygulaması olarak ayrı bir Kaydet yöntemine sahip oldukları için insanların sık sık kafalarının karıştığını gördüm. Kesinlikle bir depoda bir Kaydetme yöntemine sahip olabiliriz, ancak bu, bellek içi CUD'yi (Oluşturma, Güncelleme, Silme) ve kalıcılık yöntemlerini (veritabanında gerçek yazma / değiştirme işlemini gerçekleştiren) izole etme sorumluluğu değildir, ancak İş Birimi modelinin sorumluluğu.

Bu yardımcı olur umarım!


1

Depo bir kalıptır, bu, kodu olabildiğince yeniden kullanmak için şeyleri standartlaştırılmış bir şekilde uygulamanın bir yoludur.


1

Depo modelini kullanmanın avantajı, veri erişim katmanınızı taklit etmektir, böylece DAL kodunu çağırmadan iş katmanı kodunuzu test edebilirsiniz. Başka büyük avantajları da var ama bu benim için çok önemli görünüyor.


1
Yine de bir DAL ile dalga geçebilirsiniz, bunun kendi başına bir havuz olması gerekmez. Önemli olan nokta, hangi veri erişim stratejisini kullanırsanız kullanın, bir arayüz uygulaması gerektiğidir. Bu, IoC konteynerlerini kullanmanıza ve bir veri deposuna ihtiyaç duymadan iş kodunuzu düzgün bir şekilde test etmenize olanak tanır.
cdaq

0

Anladığım kadarıyla temelde aynı anlama gelebilirler - ancak adlandırma bağlama göre değişir.

Örneğin, bir IRepository arabirimi uygulayan bir Dal / Dao sınıfınız olabilir.

Dal / Dao bir veri katmanı terimidir; uygulamanızın daha yüksek katmanları Depolar açısından düşünür.


0

Yani (basit) vakaların çoğunda DAO bir Depo uygulaması mıdır?

Anladığım kadarıyla, DAO'nun tam olarak db erişimi (CRUD - Yine de seçim yok mu ?!) ile uğraştığı görülürken, Depo tüm veri erişimini soyutlamanıza izin verir, belki birden fazla DAO için bir cephe (belki farklı veri kaynakları).

Doğru yolda mıyım?


Aslında, bunu tersine çeviririm ve basit bir bakış açısıyla, bir Deponun bir DAO için belirli bir uygulama stili olduğunu söylerdim, ama evet, doğru yoldasınız. (CRUD'dan R = Oku, bu yüzden
seçiminiz bu

0

Bir "havuz" un belirli bir sınıf olduğu ve bir "DAL" ın depolardan, DTO'lardan, yardımcı program sınıflarından ve gerekli olan diğer her şeyden oluşan katmanın tamamı olduğu iddia edilebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.