Для меня шаблон репозитория - это создание тонкой оболочки вокруг вашей методологии доступа к данным. LINQ to SQL в твоем случае, но NHibernate, свернутый вручную в других. Я обнаружил, что создаю репозиторий для каждой таблицы, что очень просто (например, списки bruno у вас уже есть). Это отвечает за поиск вещей и выполнение операций CRUD.
Но тогда у меня есть уровень обслуживания, который больше касается совокупных корней, как упоминает Йоханнес. Я хотел бы иметь UserService с методом, подобным GetExistingUser (int id). Это вызвало бы внутренний метод UserRepository.GetById () для получения пользователя. Если ваш бизнес-процесс требует, чтобы пользовательский класс, возвращаемый GetExistingUser (), почти всегда нуждался в заполнении свойства User.IsInRoles (), тогда просто установите UserService как в UserRepository , так и RoleRepository. В псевдокоде это может выглядеть примерно так:
public class UserService
{
public UserService(IUserRepository userRep, IRoleRepository roleRep) {...}
public User GetById(int id)
{
User user = _userService.GetById(id);
user.Roles = _roleService.FindByUser(id);
return user;
}
userRep и roleRep будут созданы с вашими битами LINQ to SQL примерно так:
public class UserRep : IUserRepository
{
public UserRep(string connectionStringName)
{
// user the conn when building your datacontext
}
public User GetById(int id)
{
var context = new DataContext(_conString);
// obviously typing this freeform but you get the idea...
var user = // linq stuff
return user;
}
public IQueryable<User> FindAll()
{
var context = // ... same pattern, delayed execution
}
}
Лично я хотел бы сделать классы репозитория внутренне ограниченными и сделать общедоступными классы UserService и другие XXXXXService, так что держите своих потребителей API сервиса честными. Поэтому я снова считаю, что репозитории более тесно связаны с процессом общения с хранилищем данных, но уровень обслуживания более тесно связан с потребностями вашего бизнес-процесса.
Я часто ловил себя на том, что действительно задумываюсь над гибкостью Linq to Objects и всего такого, и использую IQuerable et al вместо того, чтобы просто создавать методы обслуживания, которые выплевывают то, что мне действительно нужно. При необходимости используйте LINQ, но не пытайтесь заставить репозиторий делать все.
public IList<User> ActiveUsersInRole(Role role)
{
var users = _userRep.FindAll(); // IQueryable<User>() - delayed execution;
var activeUsersInRole = from users u where u.IsActive = true && u.Role.Contains(role);
// I can't remember any linq and i'm type pseudocode, but
// again the point is that the service is presenting a simple
// interface and delegating responsibility to
// the repository with it's simple methods.
return activeUsersInRole;
}
Итак, это было немного бессвязно. Не уверен, действительно ли я помогал кому-либо, но я советую избегать слишком увлекательных методов расширения и просто добавить еще один слой, чтобы каждая из движущихся частей была довольно простой. У меня работает.