Я понимаю, что это старая проблема, но в последнее время я занимаюсь этой же проблемой, и я пришел к тому же выводу, что и Чад: при небольшой дисциплине гибрид методов расширения и методов хранилища, кажется, работает лучше всего.
Некоторые общие правила, которым я следовал в своем приложении (Entity Framework):
Заказ запросов
Если метод используется только для упорядочивания, я предпочитаю писать методы расширения, которые работают на IQueryable<T>
или IOrderedQueryable<T>
(чтобы использовать базового провайдера.) Например,
public static IOrderedQueryable<TermRegistration> ThenByStudentName(
this IOrderedQueryable<TermRegistration> query)
{
return query
.ThenBy(reg => reg.Student.FamilyName)
.ThenBy(reg => reg.Student.GivenName);
}
Теперь я могу использовать ThenByStudentName()
по мере необходимости в моем классе репозитория.
Запросы, возвращающие отдельные экземпляры
Если метод включает запросы по примитивным параметрам, он обычно требует ObjectContext
и не может быть легко выполнен static
. Эти методы я оставляю в своем хранилище, , например
public Student GetById(int id)
{
// Calls context.ObjectSet<T>().SingleOrDefault(predicate)
// on my generic EntityRepository<T> class
return SingleOrDefault(student => student.Active && student.Id == id);
}
Однако, если вместо этого метод включает запрос EntityObject
с использованием его навигационных свойств , его обычно можно легко сделать static
и реализовать как метод расширения. , например
public static TermRegistration GetLatestRegistration(this Student student)
{
return student.TermRegistrations.AsQueryable()
.OrderByTerm()
.FirstOrDefault();
}
Теперь я могу легко написать someStudent.GetLatestRegistration()
, не нуждаясь в экземпляре репозитория в текущей области.
Запросы, возвращающие коллекции
Если метод возвращает некоторые значения IEnumerable
, ICollection
или IList
, то я хотел бы сделать его static
, если это возможно, и оставить его в хранилище , даже если он использует свойства навигации. например
public static IList<TermRegistration> GetByTerm(Term term, bool ordered)
{
var termReg = term.TermRegistrations;
return (ordered)
? termReg.AsQueryable().OrderByStudentName().ToList()
: termReg.ToList();
}
Это потому, что мои GetAll()
методы уже живут в репозитории, и это помогает избежать беспорядочной путаницы методов расширения.
Еще одна причина, по которой эти "методы получения коллекций" не используются в качестве методов расширения, заключается в том, что им потребуется более подробное именование, чтобы иметь смысл, поскольку возвращаемый тип не подразумевается. Например, последним примером станет GetTermRegistrationsByTerm(this Term term)
.
Надеюсь, это поможет!