对我来说,存储库模式是关于在您的数据访问方法周围放置一个瘦包装器。在您的情况下使用 LINQ to SQL,但在其他情况下使用 NHibernate。我发现自己在做的是为每个表创建一个存储库,这非常简单(就像布鲁诺列表一样,你已经有了)。那是负责找东西和做 CRUD 操作的。
但是,正如 Johannes 所提到的,我的服务级别更多地处理聚合根。我将有一个像 GetExistingUser(int id) 这样的方法的 UserService。这将在内部调用 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;
}
所以,这有点漫无边际。不确定我是否真的有帮助,但我的建议是避免对扩展方法过于花哨,只需添加另一层以保持每个移动部分都非常简单。对我有用。