Opracowujemy aplikację ASP.NET MVC, a teraz budujemy klasy repozytorium / usług. Zastanawiam się, czy są jakieś główne zalety tworzenia ogólnego interfejsu IRepository, który implementują wszystkie repozytoria, w porównaniu z każdym repozytorium mającym swój własny, unikalny interfejs i zestaw metod.
Na przykład: ogólny interfejs IRepository może wyglądać (zaczerpnięty z tej odpowiedzi ):
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();
}
Każde repozytorium implementowałoby ten interfejs, na przykład:
- CustomerRepository: IRepository
- ProductRepository: IRepository
- itp.
Alternatywą, którą stosowaliśmy w poprzednich projektach, byłoby:
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);
}
W drugim przypadku wyrażenia (LINQ lub inne) byłyby w całości zawarte w implementacji repozytorium, każdy, kto implementuje usługę, musi tylko wiedzieć, którą funkcję repozytorium wywołać.
Wydaje mi się, że nie widzę korzyści z pisania całej składni wyrażeń w klasie usług i przekazywania do repozytorium. Czy nie oznaczałoby to, że łatwy do zepsucia kod LINQ jest w wielu przypadkach duplikowany?
Na przykład w naszym starym systemie fakturowania dzwonimy
InvoiceRepository.GetSingleInvoice(DateTime invoiceDate, int accountId)
z kilku różnych usług (klient, faktura, konto itp.). Wydaje się to o wiele czystsze niż pisanie tego w wielu miejscach:
rep.GetSingle(x => x.AccountId = someId && x.InvoiceDate = someDate.Date);
Jedyną wadą, jaką widzę przy stosowaniu tego konkretnego podejścia, jest to, że możemy skończyć z wieloma permutacjami funkcji Get *, ale nadal wydaje się to lepsze niż wypychanie logiki wyrażeń do klas Service.
czego mi brakuje?