Stiamo sviluppando un'applicazione ASP.NET MVC e ora stiamo creando le classi di repository / servizi. Mi chiedo se ci siano dei grandi vantaggi nella creazione di un'interfaccia IRepository generica implementata da tutti i repository, rispetto a ciascun Repository che ha la sua interfaccia unica e una serie di metodi.
Ad esempio: potrebbe apparire un'interfaccia IRepository generica (presa da questa risposta ):
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();
}
Ogni repository implementerebbe questa interfaccia, ad esempio:
- CustomerRepository: IRepository
- ProductRepository: IRepository
- eccetera.
L'alternativa che abbiamo seguito nei progetti precedenti sarebbe:
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);
}
Nel secondo caso, le espressioni (LINQ o altro) sarebbero interamente contenute nell'implementazione del repository, chiunque stia implementando il servizio deve solo sapere quale funzione di repository chiamare.
Immagino di non vedere il vantaggio di scrivere tutta la sintassi delle espressioni nella classe di servizio e passare al repository. Questo non significherebbe che in molti casi il codice LINQ facile da incasinare viene duplicato?
Ad esempio, nel nostro vecchio sistema di fatturazione, chiamiamo
InvoiceRepository.GetSingleInvoice(DateTime invoiceDate, int accountId)
da alcuni servizi diversi (Cliente, Fattura, Conto, ecc.). Sembra molto più pulito che scrivere quanto segue in più punti:
rep.GetSingle(x => x.AccountId = someId && x.InvoiceDate = someDate.Date);
L'unico svantaggio che vedo nell'uso dell'approccio specifico è che potremmo finire con molte permutazioni delle funzioni Get *, ma questo sembra ancora preferibile spingere la logica di espressione nelle classi di servizio.
Cosa mi sto perdendo?