Ми розробляємо додаток ASP.NET MVC і зараз будуємо сховища / класи обслуговування. Мені цікаво, чи є якісь основні переваги для створення загального інтерфейсу IRepository, який реалізують усі репозиторії, проти кожного репозиторію, який має свій унікальний інтерфейс та набір методів.
Наприклад: загальний інтерфейс IRepository може виглядати так (з цієї відповіді ):
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();
}
Кожен репозиторій реалізував би цей інтерфейс, наприклад:
- CustomerRepository: IRepository
- ProductRepository: IRepository
- тощо.
Замінник, який ми дотримувались у попередніх проектах, буде:
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);
}
У другому випадку вирази (LINQ або іншим чином) повністю міститимуться в реалізації Репозиторію, той, хто реалізує послугу, просто повинен знати, яку функцію репозиторію потрібно викликати.
Я думаю, я не бачу переваги в записі всіх синтаксисів виразів у клас обслуговування та переході до сховища. Чи не означатиме це, що у багатьох випадках простий у збитті код LINQ дублюється?
Наприклад, у нашій старій системі виставлення рахунків ми дзвонимо
InvoiceRepository.GetSingleInvoice(DateTime invoiceDate, int accountId)
від декількох різних послуг (Клієнт, Рахунок, Рахунок тощо). Це здається набагато чистішим, ніж писати наступне у кількох місцях:
rep.GetSingle(x => x.AccountId = someId && x.InvoiceDate = someDate.Date);
Єдиним недоліком, який я бачу при використанні конкретного підходу, є те, що ми могли б закінчитися багатьма перестановками функцій Get *, але це все ще здається кращим, ніж висунення логіки виразів до класів служби.
Що я пропускаю?