Design patterns 服务类应该不仅仅是存储库类的包装器吗?

Design patterns 服务类应该不仅仅是存储库类的包装器吗?,design-patterns,service,repository,Design Patterns,Service,Repository,我的理解是,直接从表示代码中使用数据访问例程被认为是有害的。因此,我有一个单独的存储库项目,以及一个服务项目。据我所知,服务层的典型用途是将数据访问与表示隔离开来。一切都很好 我有一个非常简单的域,就是一个电影类。匹配的存储库接口是: public interface IMovieRepository { void AddMovie(Movie movie); void UpdateMovie(Movie movie); void RemoveMovie(Movie mo

我的理解是,直接从表示代码中使用数据访问例程被认为是有害的。因此,我有一个单独的
存储库
项目,以及一个
服务
项目。据我所知,服务层的典型用途是将数据访问与表示隔离开来。一切都很好

我有一个非常简单的域,就是一个
电影
类。匹配的存储库接口是:

public interface IMovieRepository
{
    void AddMovie(Movie movie);
    void UpdateMovie(Movie movie);
    void RemoveMovie(Movie movie);
    int GetMovieCount();
    Movie GetMovieById(int id);
    IEnumerable<Movie> GetAllMovies();
    IEnumerable<Movie> GetMoviesByGenre(Genre genre);
    IEnumerable<Movie> GetMoviesByYear(int year);
    IEnumerable<Movie> GetMoviesByActor(string actor);
    IEnumerable<Movie> GetMoviesByTitle(string title);
}
公共接口存储库
{
电影(电影);
void UpdateMovie(电影);
无效删除电影(电影);
int GetMovieCount();
电影GetMovieById(int-id);
IEnumerable GetAllMovies();
IEnumerable GetMoviesBy流派(流派);
IEnumerable GetMoviesByYear(int year);
IEnumerable GetMoviesByActor(字符串演员);
IEnumerable GetMoviesByTitle(字符串标题);
}
现在,当我使用服务类来使用存储库时,我最终定义了如下接口:

public interface IMovieService
{
    Movie CreateMovie(string title, int year, Genre genre, int length, IEnumerable<string> actors);
    void UpdateMovie(Movie movie);
    void RemoveMovie(Movie movie);
    int GetMovieCount();
    Movie GetMovieById(int id);
    IEnumerable<Movie> GetAllMovies();
    IEnumerable<Movie> GetMoviesByGenre(Genre genre);
    IEnumerable<Movie> GetMoviesByYear(int year);
    IEnumerable<Movie> GetMoviesByActor(string actor);
    IEnumerable<Movie> GetMoviesByTitle(string title);
}
公共接口服务
{
Movie CreateMovie(字符串标题、整数年、体裁类型、整数长度、IEnumerable演员);
void UpdateMovie(电影);
无效删除电影(电影);
int GetMovieCount();
电影GetMovieById(int-id);
IEnumerable GetAllMovies();
IEnumerable GetMoviesBy流派(流派);
IEnumerable GetMoviesByYear(int year);
IEnumerable GetMoviesByActor(字符串演员);
IEnumerable GetMoviesByTitle(字符串标题);
}
这两个接口非常相似,这让我感到奇怪。我期望
IMovieService
实现在内部使用
IMovieRepository
实现,本质上是后者的薄包装。可能会有一些验证或缓存之类的东西,但在大多数情况下,前者似乎只是传递给后者

我这样做是对的,还是我遗漏了什么

我知道,对于这样一个简单的领域来说,这似乎有点过分了,但我正在努力确定分层和抽象的模式,以便在未来和更大的项目中使用

编辑:更清楚一点,我不是在谈论NHibernate或存储库模式,而是关于关注点的分层


更新:谢谢各位。我相信我会在服务类上保留特定的查询方法,这对于UI层来说是简单的,并尝试通过将查询传递给查询函数来概括存储库。

鉴于您定义的接口IMovieRepository,IMovieService接口是多余的。如果存储库接口是下面给出的通用接口,那么服务接口就有价值。我更喜欢更简单的存储库界面,因为对我来说,它提供了更好的关注点分离

public interface IRepository<T> {
    IQueryable<T> Fetch();
    void Save(T item);
    void Remove(T item);
}
公共接口IRepository{
IQueryable Fetch();
作废保存(T项);
消除无效(T项);
}

拥有一个服务类来简单地包装存储库是不必要的复杂性

我通常都会尝试一下。。。方法(TrySave、TryDelete等),然后添加错误消息作为out参数。我只让存储库处理持久性问题——将其放入和移出存储库

至于查询,我不会让它通过我的服务,除非我有以用户界面为中心的复杂过滤对象,需要在它们进入存储库之前进行“转换”


希望这有帮助

我通常喜欢在我的服务类中放置更复杂的查询。调用某个存储库方法,然后使用其他Linq to Object方法生成所需数据集的方法

我认为你是对的。DataAccess API和ServiceAPI看起来如此相似的原因是您还没有为您的服务提供任何真正的业务逻辑。下面是一些头脑风暴,它们可能最终会出现在您的服务API上,但会涉及一些比简单的CRUD(创建、读取、更新、删除)功能更复杂的操作。显然,这些只是快速而肮脏的例子,但我相信你会明白:

  • 推荐电影(int movieID,string friendEmail)
  • RateMovie(int movieID,int numberOfStars)
  • AddMovieToMyWishList(int-movieID,int-userID)
我认为ServiceLayer和DataLayer的分离是一个重要而有价值的分离,你不应该猜测它,即使这两个api目前非常相似。随着服务功能的增长,这两个API将继续分化,以满足调用者的需求