Genel Veri Havuzu EF 4.1 ile nokta nedir


145

DbContext, DbSet ve ilgili arabirimlere daha derine inerken, neden bu uygulamalar etrafında ayrı bir "Genel" Depo uygulamanız gerektiğini merak ediyorum?

Görünüşe göre DbContext ve IDbSet ihtiyacınız olan her şeyi yapıyor ve DbContext'in içinde "İş Birimi" ni içeriyor.

Burada bir şey mi özlüyorum yoksa insanlar sebepsiz yere başka bir bağımlılık katmanı eklemekten hoşlanıyor mu?


Bu biraz tartışmalı / fikir temelli bir konudur. Bu tartıştık burada .
Amit Joshi

Yanıtlar:


202

Aslında haklısın. DbContextçalışma düzeni biriminin IDbSetbir uygulamasıdır ve arşiv modelinin bir uygulamasıdır.

Depolar şu anda çok popüler ve gereğinden fazla kullanılıyor. Herkes bunları kullanıyor çünkü varlık çerçevesi için depo oluşturmayla ilgili düzinelerce makale var ama kimse bu kararla ilgili zorlukları tanımlamıyor.

Depo kullanmanın ana nedenleri genellikle şunlardır:

  • EF'yi üst katmandan gizle
  • Kodu daha iyi test edilebilir hale getirin

İlk neden, bir tür mimari saflık ve üst katmanlarınızı EF üzerinde bağımsız hale getirirseniz, daha sonra diğer kalıcılık çerçevesine geçebileceğiniz harika bir fikirdir. Gerçek dünyada kaç kez böyle bir şey gördün? Bu neden, EF ile çalışmayı çok daha zor hale getirir, çünkü deponuzun EF'in varsayılan olarak izin verdiği şeyleri saran birçok ek özelliği açığa çıkarması gerekir.

Aynı zamanda EF kodunu sarmak, kodunuzu daha iyi organize edebilir ve Ayrılma kaygısı kuralını takip edebilir. Benim için bu, havuzun ve çalışma biriminin tek gerçek avantajı olabilir, ancak EF ile bu kurala uymanın kodunuzu daha iyi korunabilir ve daha iyi okunabilir hale getireceğini anlamalısınız, ancak uygulamanızı oluşturmak için ilk çabanız çok daha yüksek olacaktır ve daha küçük uygulamalar için bu gereksiz karmaşıklık olabilir.

İkinci neden kısmen doğrudur. EF'nin en büyük dezavantajı, neredeyse alay edilemeyen katı mimaridir; bu nedenle, üst katmanı birim testi yapmak istiyorsanız, uygulamasının alay edilmesine izin vermek için EF'i bir şekilde sarmalısınız. Ancak bunun, burada anlattığım birçok başka sonucu vardır .

Ayende'nin blogunu takip ediyorum . NHibernate'i daha önce kullandıysanız, muhtemelen makalelerini biliyorsunuzdur. Bu adam yakın zamanda NHibernate ile depo kullanımına karşı birkaç makale yazdı, ancak NHibernate çok daha iyi alay edilebilir.


3
Alay IDbSetedebilirsiniz, türetilmiş bağlamınızda özel arayüz de tanımlayabilirsiniz, ancak hepsi bu. Kodunuz ChangeTracker, Entries veya başka herhangi bir şeyi kullandığında, hepsini sarmak için büyük çaba gerektirecektir.
Ladislav Mrnka

1
Evet EF çok performans odaklı bir araç değildir. En azından MS, gelecekteki sürümlerde bunu daha iyi hale getirmek için birçok fırsata sahiptir.
Ladislav Mrnka

2
@chiccodoro: Doğru. Ancak alay edilen sınıfınız , Linq-to-varlık sorgusuna dahili olarak yerleştirilen parametre olarak ortaya çıktığında IQueryableveya kabul Expression<>ettiğinde, alay edilen bileşenin dışında, birim testlerle test edilemeyen yan etkileri olan mantığı tanımlarsınız.
Ladislav Mrnka

8
DbSet ve BdContext'i doğrudan iş katmanımda kullanıyorsam, orada ve DataLayer projemde EntityFramework.dll'ye başvurmam gerekir. Tek başına bu bana bir çeşit sargıya ihtiyacı olduğunu söylüyor.
Ingó Vals

2
olumsuz oy: eksik - bir depo arabiriminin arkasında EF'in soyutlanması, aynı istemci kodunun hem SL hem de WPF'de çalışmasını sağlayabilir.
h.alex

21

Aynı sorunlarla mücadele ediyorum ve EF katmanlarının birim testi için alay edilebilirlik önemlidir. Ancak türetilmiş DbContext'inizin genel bir arabirim uyguladığından ve DbSet'ler yerine IDbSet'i ortaya çıkardığından emin olarak EF 4.1 DbContext'in alay edilebilir olacak şekilde nasıl ayarlanacağını açıklayan bu harika makaleye rastladım. Database First yaklaşımını kullandığım için, veritabanımız zaten mevcut olduğundan, türetilmiş DbContext'imi oluşturmak için kullanılan T4 şablonlarını değiştirerek IDbSet arayüzlerini döndürmek ve genel arayüzümden türetmek için basitçe değiştirdim. Bu şekilde, her şey kolayca alay edilebilir ve kendi Çalışma Biriminizi veya arşiv modelinizi uygulamanıza gerek kalmaz. Genel arayüzünüzü kullanmak için servis kodunuzu yazmanız yeterlidir ve ünite testine gittiğinizde,

http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/


5

Depoyu oluşturmanın bir nedeni, EntityFramework'dan başka bir şeye veya tam tersine geçmeye karar verirseniz DBSet ve DbContext uygulamalarını gizleyebilmenizdir.

Örneğin, NHibernate kullanıyordum ve bu çerçeveye yapılan tüm çağrıları depo sınıflarımın içine sardım. "Genel" olması için IEnumerable'ı döndürüyorlar ve depolarımda standart CRUD işlemleri var (güncelleme, silme, vb.). Uzun zamandır Entity Framework'e taşındım. Bunu yaptıktan sonra, ViewModel sınıflarımda veya ötesinde hiçbir şeyi değiştirmeme gerek kalmadı, çünkü bunlar depomu işaret ediyorlardı - sadece depomun içini değiştirmem gerekiyordu. Bu, göç ederken hayatı çok daha kolaylaştırdı.

(NHibernate'i kullandım çünkü ISeries'e bağlanıyoruz ve o zamanlar ISeries ile EF kullanan hiçbir maliyet etkili uygulamalar yoktu. Mevcut tek seçenek, DB2Connect'leri için IBM'e 12.000 $ ödemekti)


"Neredeyse" (DBSet ve DbContext'i gizleme konusunda) EF'i herhangi bir tüketiciye göstermeniz gerekmediğini (örneğin DI'dan yararlanıyorsanız) ancak IDbSet <T> özelliklerini açığa çıkaran bir arabirime ihtiyacınız olduğunu göreceksiniz veya bir adım daha ileri gidin ve bunun yerine tüm özelliklerinizi IQueryable <T> 'ler olarak yazın, ancak benim amacım DbSet ve DbContext'e olan bağımlılığınızı tamamen gizleyebilmenizdir. CRUD operasyonları daha sonra uzantı yöntemleri olarak yazılabilir, farklı destek depoları için birden fazla uzantı yöntemi yazabilirsiniz. Bununla birlikte, LINQ kullanımını saklamazsınız.
Shaun Wilson
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.