【问题标题】:Repository pattern and service layer implementation存储库模式和服务层实现
【发布时间】:2013-05-23 23:28:21
【问题描述】:

我正在为我的 mvc4 网站使用通用存储库和工作单元模式。

现在我有一种情况,我想删除我系统的一个用户。 在删除代码中,我必须删除其他表中的一些条目(cmets、accessrights、..)。

最简单的解决方案是创建一个UserRepository,它继承自GenericRepository<User>,并修改delete方法删除其他表中的数据。但这意味着我的UserRepository 可以访问其他表,这些表应该有自己的存储库类,对吧?

我读过一个服务层,它位于我的业务逻辑和我的存储库之间。

这里的最佳实践是什么?服务层的实现如何?

如果我使用服务层或者我应该只有通用存储库并在服务类中执行我的逻辑,是否仍然需要自定义实现的存储库,例如 UserRepository

示例代码:

class UserRepository
{
    public void Delete(User entity)
    {
        var userComments = Context.UserComments.Get(comment => comment.UserId == entity.Id);

        foreach (var comment in userComments)
        {
            Context.UserComments.Remove(comment);
        }

        //
        // same for access rights here
        //

        Context.Users.Remove(entity);
    }
}

【问题讨论】:

  • 避免手动执行此操作的一种方法是利用 CASCADE DELETE...(查看映射中的 .WillCascadeOnDelete())
  • 删除代码只是一个例子,我有更多的查询可以访问多个表,例如用于为用户返回报告数据。

标签: c# asp.net-mvc-4 repository-pattern


【解决方案1】:

使用

.WillCascadeOnDelete(true);

modelBuilder

回答您有关服务的问题。理想情况下,您希望您的服务对存储库为您检索的实体/对象执行附加逻辑。在这种情况下,您并不真正希望服务删除行,因为这是您的存储库的责任。

服务很好。在 MVC 中,您从控制器调用服务方法。理想情况下,接口可以让您轻松测试它们。

【讨论】:

  • 根据Matt Roberts 的回答:哪个职责有repository,哪个service?我不明白这里的区别。
  • 在我看来,服务将所有内容包装在一个很好的可用对象中,以供您的控制器使用。将常见任务作为公共方法放入服务中,如果没有服务,这些常见任务将与对控制器或帮助器类或其他东西中的存储库方法的调用混合在一起。理想情况下,你有一个轻量级的控制器,它只是做它应该做的;将内容返回给视图并从视图中获取内容。该服务完成所有繁重的工作。存储库使用 ORM 或 SQL 或其他任何东西来获取或知道如何从您的数据源获取(执行 CRUD)数据。
  • 是的 - 简单的数据操作是存储库的工作 - 所以你不会从这里的服务中得到任何东西。但是假设您需要合并来自 2 个来源的用户以创建一个主列表 - 这对于服务类来说是一个很好的案例 - 它可以在内部调用 2 个不同的 reopisitories 来获取数据
  • 很好的例子。我会务实地说,一旦你的控制器开始变大,就重构为一个服务类。
  • 实际上我正在使用 AutoMapper 创建 ViewModel 以将内容返回到我的视图中。如果我理解正确,服务类可以取代 AutoMapper 的需要,因为我有可能在服务中创建 ViewModel?
【解决方案2】:

正如您所说,服务层可以帮助您将业务逻辑和存储库分开。这里的主要思想是依赖注入

public interface IUserService
{
    public void Delete(User entity);
}

//
// This class would be used Linq to Entities 
public class LinqUserService : IUserService 
{
    public void Delete (User entity)
    {
    }  
}

// 
// This class would be used Sql command
public class SqlUserService : IUserService
{
    public void Delete (User entity)
    {
    } 
}

【讨论】:

  • 我正在使用 Ninject 将我的 UnitOfWork 类注入到我的控制器中。您的意思是应该针对哪些类进行哪种注入?
【解决方案3】:

存储库模式随着 DDD(领域驱动设计)运动而普及。在 DDD 中,建议您不要为每个表创建一个存储库,而是为每个聚合根创建一个存储库。因此,虽然您可能有一个用于用户、用户订单和用户 cmets 的表,但您可以决定用户是聚合根,然后您只需创建一个用户存储库并在那里添加您的方法。

无论如何,无论您是否关心 DDD,我都会将逻辑添加到您的用户存储库中,在那里而不是任何其他存储库是有意义的。

可以为此创建一个服务层并创建一个服务类,但服务类对此实际上没有用 - 在这种情况下您并没有真正受益。

【讨论】:

  • 这很有趣,我理解为每个表只有一个存储库。
  • 通用 repos 很好,但不要害怕向它们添加逻辑。你需要删除一个用户,这应该是你的用户 reop 上的一个方法,它也应该删除用户 cmets 等。
猜你喜欢
  • 2017-09-19
  • 2016-10-07
  • 1970-01-01
  • 2011-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
相关资源
最近更新 更多