N-katmanlı Entity Framework çözümü ile bağımlılık enjeksiyonu


12

Şu anda, veri erişim stratejisi olarak Entity Framework 5'i (.net 4) kullanan n katmanlı bir çözüm tasarlıyorum, ancak test edilebilir / esnek hale getirmek için bağımlılık enjeksiyonunu nasıl dahil edeceğim konusunda endişeliyim.

Mevcut çözüm düzenim aşağıdaki (çözümüm Alcatraz olarak adlandırılıyor):

Alcatraz.WebUI : Bir asp.net webform projesi, ön uç kullanıcı arayüzü, Alcatraz.Business ve Alcatraz.Data.Models projelerine referans veriyor .

Alcatraz.Business : Bir sınıf kütüphane projesi, iş mantığını içerir, referans projeleri Alcatraz.Data.Access , Alcatraz.Data.Models

Alcatraz.Data.Access : Bir sınıf kütüphane projesi, AlcatrazModel.edmx ve AlcatrazEntitiesDbContext'e ev sahipliği yapar, Alcatraz.Data.Models projelerine referans verir .

Alcatraz.Data.Models : Bir sınıf kütüphanesi projesi, Alcatraz modeli için POCO içerir, referans yok.

Bu çözümün nasıl işleyeceğine dair vizyonum, web-ui'nin iş kütüphanesinde bir havuz oluşturmasıdır, bu havuzun bir bağlantı dizesine ( AlcatrazEntitiesörnek değil) bağımlılığı (yapıcı aracılığıyla ) olacaktır. Web-ui veritabanı bağlantı dizelerini bilir, ancak bu bir varlık çerçevesi bağlantı dizesi değildir.

İşletme projesinde:

public class InmateRepository : IInmateRepository
{
    private string _connectionString;

    public InmateRepository(string connectionString)
    {
        if (connectionString == null)
        {
            throw new ArgumentNullException("connectionString");
        }

        EntityConnectionStringBuilder connectionBuilder = new EntityConnectionStringBuilder();

        connectionBuilder.Metadata = "res://*/AlcatrazModel.csdl|res://*/AlcatrazModel.ssdl|res://*/AlcatrazModel.msl";
        connectionBuilder.Provider = "System.Data.SqlClient";
        connectionBuilder.ProviderConnectionString = connectionString;

        _connectionString = connectionBuilder.ToString();
    }

    public IQueryable<Inmate> GetAllInmates()
    {
        AlcatrazEntities ents = new AlcatrazEntities(_connectionString);

        return ents.Inmates;
    }
}

Web kullanıcı arayüzünde:

IInmateRepository inmateRepo = new InmateRepository(@"data source=MATTHEW-PC\SQLEXPRESS;initial catalog=Alcatraz;integrated security=True;");

List<Inmate> deathRowInmates = inmateRepo.GetAllInmates().Where(i => i.OnDeathRow).ToList();

Bu tasarımla ilgili birkaç sorum var.

  1. Bu tasarım Varlık Çerçeveleri yetenekleri açısından bile anlamlı mı? Entity çerçevesinin zaten Çalışma Birimi kalıbını kullandığını duydum, sadece gereksiz bir şekilde başka bir soyut katman ekliyor muyum?

  2. Web kullanıcı arayüzümün Entity Framework ile doğrudan iletişim kurmasını istemiyorum (hatta bu konu için referansta bulunuyorum), tüm veritabanı erişiminin iş katmanından geçmesini istiyorum, gelecekte aynı iş katmanını kullanan birden fazla projeye sahip olacağım (web servisi, windows uygulaması vb.) ve iş mantığının tek bir merkezi alanda bulunmasını kolay bir şekilde sürdürmesini / güncellemesini istiyorum. Bunu başarmanın uygun bir yolu var mı?

  3. Business katmanı depolar içermeli mi, yoksa Access katmanı içinde mi yer almalı? Eğer bulundukları yer uygunsa, bir bağlantı dizesini geçmek iyi bir bağımlılık mıdır?

Okumak için zamanınızı ayırdığınız için teşekkürler!

Yanıtlar:


11

DI yapma şekliniz yanlış.

İlk olarak, bağlantı dizesi veri katmanına aittir. Veya web.config dosyasında.

Ele alacağınız bir sonraki soyutlama bir bağlantı dizesi değil, DbContext'dir. Depolarınız bağlantı dizeleri hakkında bilgi sahibi olmamalıdır. İş mantığınız DbContext vb. Hakkında bilgi sahibi olmayacak.

Kullanıcı arayüzünüzün hiçbir fikri olmayacak ve EF ile ilgili hiçbir şey başlatmayacaktır.

Puanlarınıza somut cevaplar:

  1. EF konusuna aşina olana kadar soyutlamalar eklemeyin. Zaten UoW, sorgular, POCO'lar vb. Kullanarak iyi soyutlamalar ekliyor.

  2. DI'nin çalışması için gereken tüm bileşenlere başvuran bir Kompozisyon Kökünüz var. Bu WebUI projesinde olabilir veya olmayabilir. Değilse, EF veya herhangi bir veri ile ilgili teknolojiye başvurmamasını beklemelisiniz.

  3. Burada dur. Soyutlamalara soyutlama eklemeyi bırakın. Doğrudan ve 'saf' mimariyle başlayın ve zaman içinde geliştirin.

Soyutlamalar karmaşıklıkla başa çıkmak için bir araçtır. Karmaşıklığın olmaması, soyutlamaya gerek olmadığı anlamına gelir (henüz).


Ne dediğini anladığım kadar açık olmak gerekirse: (arabirimin iş dünyasında var olduğu ve somut Alcatraz.Data.Access'te var olduğu) depo DbContextbir bağımlılığını kabul eder . İşletme sınıflarının bir bağımlılığı olarak depoları vardır. Bağımlılık enjeksiyonu için, bunu manuel olarak yapıyorum (bu yüzden neler olduğunu anlıyorum). Üzerinde bağlantı dizesini ayarlamak istiyorum nedeni ben DbContextbazı durumlarda (aynı yapının) farklı veritabanlarına bağlanmak için varlık çerçeve olması gerekir böylece veritabanı parçalama kullanmaktır. Seni doğru anladım mı?
Matthew

Sağladığınız koddan, hiç DI yapmıyorsunuz gibi görünüyor. DI'nin temel amacı sizi ve kodunuzu bağımlılıkları yönetmekten kurtarmaktır. DI kabı olmadan elle etkili bir şekilde yaptığınızı hayal edemiyorum.
Boris Yankov

DI ile de zihninizi açık tutun. Ben zaten, eğlence için, tam olarak aynı soru burada daha sonra diğer forumda zıt cevaplar almak istedi. DI bir mimari değil bir örüntüdür. Hedefinize bağlı olarak onu kullanmaya veya kullanmaya karar verebilirsiniz. Kullanıyorum ama çoğu insan bana kullanmamı söylediği nedenlerden dolayı değil.
Bastien Vandamme

4

Birkaç hızlı yorum. Şahsen ben bir bağlantı dizesini geçmek olmaz. Bir şey denemek ve arayüzleri oluşturmak için belki de depolar için ve sadece arayüzleri etrafında geçmek? Depoların bir IOW arabirimini uygulamasını veya göstermesini sağlayın.

Bu şekilde olayın depolarınızı uygulayan bir veritabanı olması gerekmez. bellek önbelleğinde olabilirler. Belki o zaman bunları örneklemek için bir çeşit bağımlılık enjeksiyon çerçevesi kullanabilirsiniz?

Bazı sorularınıza cevap olarak:

  1. Evet, bence sorun yok
  2. Yine de EF deposunun EF projesine ve EF veri havuzu katmanının uyguladığı iş katmanı referans arabirimlerine sahip olurdum. Bu şekilde başka projeler de aynı montajları kullanabilir, ancak istenirse takas etme esnekliğine sahip olurlar mı?
  3. hmmm, Muhtemelen erişim katmanındaki depolar ama iş katmanı maruz bir arayüz tanımı uygulamak ??

Bunlar üzerinde düşünülmesi gereken bazı düşünceler.


2. nokta hakkında, yapmaya çalıştığım bir hedef, doğrudan ui katmanı içinde CRUD olmamasını sağlamak. Demek istediğim, iş katmanından geçerek sadece CRUD'un olmasını sağlamak istiyorum, bu şekilde yönetiliyor.
Matthew
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.