【问题标题】:Is Db access from my Services Layer a bad thing?从我的服务层访问数据库是一件坏事吗?
【发布时间】:2013-11-19 20:56:39
【问题描述】:

我的上一个应用程序实现了 UoW、DI、IoC、存储库模式、工厂,以及各种看起来很整洁的东西,但让维护和调试变得很痛苦。

我对我最近的应用程序采取了相反的方法 - 没有 DI、没有 IoC、没有 UoW,只有 MVC、服务层和 DB。我可能认为存储库模式全错了,但我所做的阅读表明它只负责 Db 访问,而不是业务逻辑,以使这两个问题分开。

在实现存储库模式时,我觉得我只是在复制我的很多服务层。例如,在我的 UserService 类中,我有以下内容:

    public void UpdateAboutMe(AboutMeDto request)
    {
        using (var db = CreateContext())
        {
            var user = db.Users.FirstOrDefault(s => s.Username.Equals(request.Username, StringComparison.OrdinalIgnoreCase));
            if (user != null)
            {
                user.AboutMe = request.AboutMe;
                SaveChanges(db);
            }
            else
            {
                throw new InvalidDataException("Null User");
            }
        }
    }

这样,Service 会抓取对象,更新单个字段,并将更改提交到 DB,然后释放上下文。

在我的 UserService 中,我还有其他类似的方法:

  • GetUserByUserName
  • GetUserById
  • GetUsersWithChildEntities
  • GetUsersWithoutChildEntities(比前者更快,对吧?)
  • 更新用户缩略图
  • UpdateUserBio
  • 更新用户兴趣

难道不是每一个都需要相应的 Repo 方法吗?

如果我实现一个存储库方法,上面的服务可能如下所示:

public void UpdateAboutMe(AboutMeDto request)
        {
            return _userRepository.UpdateAboutMe(request);
        }

这看起来更干净,但不是 lot 更干净,因为我只是在移动东西 - 如果我决定更改我的一个 Get 方法以包含一些子实体,我现在必须在 Repo 中创建另一个方法,更新接口,更新 Service 方法,而不是直接从我的服务方法中进行。

基于我上面展示的有限理解,我基本上有兴趣了解我是否应该实施存储库模式。看起来它要么为您的应用程序增加了一个垂直层的复杂性,要​​么只是让您的服务层更加强大。

IMO - 使用 EF 延迟加载和按字段更新 - 存储库模式的开销似乎要大得多。

而且,在这种情况下,我并不热衷于 TDD,因此如果可能的话,我希望将可测试性排除在外。

【问题讨论】:

    标签: c# asp.net repository-pattern


    【解决方案1】:

    存在解决问题的模式。如果模式解决问题的方式引入了其他在您的环境中不可接受的方式,那么要么您做错了,要么您只需要走另一条路。

    除此之外,仅仅因为某些东西是一种模式并不意味着你应该盲目地使用它。由于引入大量代码而收益相对较小,因此我认为有许多“模式”是纯粹的垃圾。

    我不知道为什么你有一个方法调用来更新单个记录上的单个字段。这似乎使事情变得有些困难,并且肯定会导致大量数据库查询在只有一个可以执行的情况下触发,从根本上破坏性能而无济于事。

    两个例子:

    GetUser(String userName, Int32 id, Boolean withEntities);
    

    GetUser(String userName, Boolean withEntities);
    GetUser(Int32 id, Boolean withEntities);
    

    第一个结合了您获取特定用户帐户的常用方法。第二个复制代码,但将其拆分。稍后您可能会决定在某个时候添加GetUser(String email, Boolean withEntities)

    您拥有的各种UpdateUser... 方法我将合二为一。将一个完整的 User 对象传递给它,并让一个方法更新整个事物。在极少数情况下,我会让方法只更新一个字段。

    【讨论】:

    • 感谢您的回答。我有一些问题:“很多 DB 查询要在一个人会做的时候触发,” - 我的客户端应用程序向仅包含 ID 和 AboutMe 的 API 控制器发送请求(以保持有效负载最小) - API 控制器调用相应的服务方法,这样我就不会重新分配不需要重新分配的字段。我看不出这会如何产生不必要的数据库调用——字段限制是故意的。想法?
    • 所以,有人在他们自己的用户编辑页面上。他们决定更改姓名、出生日期和关于我的信息。会发生什么......是否进行了 3 个 DB 调用?如果是这样,那么 API 是错误的。这个网站就是一个很好的例子,去编辑你的个人资料吧。您将看到 7 个需要更改的潜在字段。我保证当有人点击保存时 SO 不会发出 7 db 调用。
    • 这不是一个表单 - 假设他们一次只更新一个字段 - 没有“同时保存所有这些”。
    • 正常用法是什么?他们是否正在浏览并做出改变?也许我不理解布局,因为我看不出这是一件好事。
    • 正常使用是内联、AJAX、每个字段更新。不过,这正在进入用户体验:p
    【解决方案2】:

    如果您对 TDD、IoC/DI 或可重用性不感兴趣,则无需过多的层。每个层都有一个目的,但如果你没有那个目的,你就不需要那个层。

    但是,一旦服务器中断期间人们开始死亡,重写内容将变得更加困难。

    【讨论】:

      猜你喜欢
      • 2010-09-22
      • 1970-01-01
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-05
      • 2020-11-28
      • 1970-01-01
      相关资源
      最近更新 更多