Wir entwickeln eine ASP.NET MVC-Anwendung und erstellen jetzt die Repository- / Serviceklassen. Ich frage mich, ob die Erstellung einer generischen IRepository-Schnittstelle, die von allen Repositorys implementiert wird, wesentliche Vorteile bietet, während jedes Repository über eine eigene Schnittstelle und einen eigenen Methodensatz verfügt.
Beispiel: Eine generische IRepository-Schnittstelle könnte folgendermaßen aussehen (aus dieser Antwort entnommen ):
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();
}
Jedes Repository würde diese Schnittstelle implementieren, zum Beispiel:
- CustomerRepository: IRepository
- ProductRepository: IRepository
- etc.
Die Alternative, der wir in früheren Projekten gefolgt sind, wäre:
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);
}
Im zweiten Fall wären die Ausdrücke (LINQ oder anderweitig) vollständig in der Repository-Implementierung enthalten. Wer auch immer den Service implementiert, muss nur wissen, welche Repository-Funktion aufgerufen werden soll.
Ich glaube, ich sehe nicht den Vorteil, die gesamte Ausdruckssyntax in die Serviceklasse zu schreiben und an das Repository zu übergeben. Würde dies nicht bedeuten, dass in vielen Fällen leicht zu verwirrender LINQ-Code dupliziert wird?
In unserem alten Rechnungsstellungssystem rufen wir beispielsweise an
InvoiceRepository.GetSingleInvoice(DateTime invoiceDate, int accountId)
von einigen verschiedenen Diensten (Kunde, Rechnung, Konto usw.). Das scheint viel sauberer zu sein, als an mehreren Stellen Folgendes zu schreiben:
rep.GetSingle(x => x.AccountId = someId && x.InvoiceDate = someDate.Date);
Der einzige Nachteil, den ich bei der Verwendung des spezifischen Ansatzes sehe, besteht darin, dass wir möglicherweise viele Permutationen von Get * -Funktionen erhalten, dies scheint jedoch immer noch vorzuziehen, um die Ausdruckslogik in die Service-Klassen zu verschieben.
Was vermisse ich?