SORU
5 AĞUSTOS 2009, ÇARŞAMBA


Her nesne için özel depo vs genel bir depo oluşturma avantajı?

ASP.NET MVC bir uygulama geliştiriyoruz, ve şimdi/hizmet sınıflarına göre depo binası vardır. Eğer tüm depoları, Depo vs her yöntem kendine özgü arayüzü ve set olması uygulayan genel bir İRepository arayüz oluşturma için herhangi bir büyük avantajı olup olmadığını merak ediyorum.

Genel İRepository bir arayüz gibi (this answer alınan) görünebilir: . örneğin:

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();
}

Her Depoyu bu arayüz, örneğin uygulamaya koyacak:

  • CustomerRepository:İRepository
  • ProductRepository:İRepository
  • vb.

Önceki projeleri takip ettik alternatif olabilir:

public interface IInvoiceRepository : IDisposable
{
    EntityCollection<InvoiceEntity> GetAllInvoices(int accountId);
    EntityCollection<InvoiceEntity> GetAllInvoices(DateTime theDate);
    InvoiceEntity GetSingleInvoice(int id, bool doFetchRelated);
    InvoiceEntity GetSingleInvoice(DateTime invoiceDate, int accountId); //unique
    InvoiceEntity CreateInvoice();
    InvoiceLineEntity CreateInvoiceLine();
    void SaveChanges(InvoiceEntity); //handles inserts or updates
    void DeleteInvoice(InvoiceEntity);
    void DeleteInvoiceLine(InvoiceLineEntity);
}

İkinci durumda, bu ifadeleri () ETMENİZ veya başka türlü tamamen hizmet sadece arama fonksiyonu olan bilmeli uygulayan her kimse Depo uygulaması, içerdiği olur.

Hizmet sınıftaki tüm ifade sözdizimi yazma ve depoyu geçen avantajını göremiyorum sanırım. Bu kolay messup ETMENİZ kodu birçok durumda yineleniyor anlamına gelmez mi?

Eski fatura sistemimizde örneğin, diyoruz

InvoiceRepository.GetSingleInvoice(DateTime invoiceDate, int accountId)

birkaç farklı hizmetler (Müşteri, Fatura, Hesap, vb.). Birden çok yerde: aşağıdaki yazı daha çok daha temiz görünüyor

rep.GetSingle(x => x.AccountId = someId && x.InvoiceDate = someDate.Date);

Özel yaklaşım kullanarak gördüğüm tek dezavantajı* işlevlere sahip birçok permütasyon ile sonuçlanabilir, ama bu yine de ifade mantığı Hizmet sınıfları içine itmek için tercih edilebilir görünüyor.

Neyi kaçırıyorum?

CEVAP
5 AĞUSTOS 2009, ÇARŞAMBA


Bu bir sorun, Depo desen kendisi kadar eskidir. SERİ son giriş IQueryable, sorgu düzgün bir temsili, bu çok konu hakkında bir çok tartışma yarattı.

Özel havuzları kendimi çok zor depo genel bir çerçeve oluşturmak için çalıştıktan sonra tercih ederim. Bir depo alanı modellenen bir parçasıdır, ve etki alanı, genel değil. denedim ne olursa olsun, hep aynı sorun oldu: Her varlık silinebilir varlık eklenebilir her değil, her varlık bir depo var. Sorgular çılgınca değişir; depo API varlık kendisi gibi eşsiz olur.

Sık kullandığım bir kalıp özel depo arabirimleri, ama uygulamaları için bir temel sınıf var. Örneğin, SERİ SQL kullanarak yapabilirsin:

public abstract class Repository<TEntity>
{
    private DataContext _dataContext;

    protected Repository(DataContext dataContext)
    {
        _dataContext = dataContext;
    }

    protected IQueryable<TEntity> Query
    {
        get { return _dataContext.GetTable<TEntity>(); }
    }

    protected void InsertOnCommit(TEntity entity)
    {
        _dataContext.GetTable<TEntity>().InsertOnCommit(entity);
    }

    protected void DeleteOnCommit(TEntity entity)
    {
        _dataContext.GetTable<TEntity>().DeleteOnCommit(entity);
    }
}

Birim çalışma seçimi DataContext değiştirin. Örnek bir uygulama olabilir:

public interface IUserRepository
{
    User GetById(int id);

    IQueryable<User> GetLockedOutUsers();

    void Insert(User user);
}

public class UserRepository : Repository<User>, IUserRepository
{
    public UserRepository(DataContext dataContext) : base(dataContext)
    {}

    public User GetById(int id)
    {
        return Query.Where(user => user.Id == id).SingleOrDefault();
    }

    public IQueryable<User> GetLockedOutUsers()
    {
        return Query.Where(user => user.IsLockedOut);
    }

    public void Insert(User user)
    {
        InsertOnCommit(user);
    }
}

Depoyu ortak API kullanıcılar silinmesine izin vermiyor dikkat edin. Ayrıca, IQueryable açığa solucanlar bambaşka bir şey - bu konuda göbek deliğine kadar birçok görüş var.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ADDVOiCE

    ADDVOiCE

    28 Mayıs 2009
  • MysteryGuitarMan

    MysteryGuita

    16 HAZİRAN 2006
  • Plugable

    Plugable

    19 Mayıs 2010