【问题标题】:Application service layer as static classes应用服务层作为静态类
【发布时间】:2011-01-18 00:54:28
【问题描述】:

在我的 ASP.NET MVC 应用程序中,我有一个包含所有业务逻辑/服务层的项目。该项目与位于单独项目中的我的数据库(实体框架)交互。

我想轻松访问服务层,因此我在其中创建了静态类,以便可以轻松引用它们。例如,如果我在控制器中并且需要创建一个新帐户:

 ServiceLayer.Accounts.CreateAccount(userName, passWord) //etc..

然后服务层执行所有需要的逻辑,然后通过DatabaseLayer 中的存储库创建用户。

    private static AllRepos _Repos;
    private static AllRepos Repos { 
       get 
        { 
           if(_Repos == null)
              _Repos = new AllRepos();

           return _Repos
        }
    }

    public static void CreateAccount(string username, password)
    {
        string salt = GenerateSalt();
        Account newAccount = DatabaseLayer.Models.Account
              { 
              Name = username,
              Password = HashPassword(password, salt),
              Salt = salt
              };
        Repos.AddAccount(newAccount);      
    }

因为我不想在服务层的任何地方都执行以下操作:

 AccountRepository Accounts = new DatabaseLayer.AccountRepository();

我改为为我的存储库创建了一个包装类,这样我只需实例化一次即可使用所有其他存储库。

 public class AllRepos
 {

    private AccountRepository _Accounts;

    public AccountRepository Accounts
    {
        get
        {
            if (_Accounts== null)
                _Accounts= new AccountRepository();

            return _Accounts;
        }
    }

    // the same is done for every other repository (currently have about 10+)
  }

在服务层的静态类中使用。

因为我所有的服务层类都是静态的,而 Repos 字段也是静态的,所以我一直遇到的一个明显问题是从多个数据上下文中检索到同一个对象会导致更新/删除的奇怪行为。

我知道,如果我像使用静态成员/类一样使用静态成员/类,因为它们持续应用程序的生命周期,这是可以预料的,但是有没有办法能够将服务层用作 ServiceLayer.Accounts.Method() 而不必创建一个非静态类,该类需要在使用它的任何地方进行实例化,并且不会因多个数据上下文实例而遇到 CRUD 问题?

【问题讨论】:

  • "事实上一些最好的辅助方法是静态的" 你对“最好”的概念是什么?

标签: asp.net-mvc entity-framework static-classes


【解决方案1】:

我不确定您为什么如此坚决反对使用实例。除了您现在拥有的代码不必要地复杂之外,使用静态类型还会使单元测试变得更加困难。静态类型就像你不能模拟/替换的单例。在我看来,您真正的问题可能是,“我如何终身管理我的服务层的实例?”通常,您通过为每个 Web 请求创建一个实例来实现这一点。在 ASP.NET MVC 应用程序中,您可以new up a DI container via a ControllerFactory, and handle all of this. [PDF]

【讨论】:

    【解决方案2】:

    您的方法确实不值得推荐。就我个人而言,我绝不会允许我的团队采用这种方法。缺点:

    1. 您遇到的主要线程问题并不容易解决
    2. 您根本无法很容易地对此进行测试。
    3. 对数据访问的抽象不切实际

    创建存储库实例的最大原因是您可以在需要时注入依赖项。对此最著名的论点是单元测试,因此您可以模拟依赖关系,但我已经构建了许多具有接口依赖关系的存储库,这些依赖关系在生产代码中会发生变化。

    无论如何,您都应该简单地将存储库实例化为基础服务类的一部分。没有理由必须是“到处都是静态 OR 实例调用”。基类中应该有有限的实例实例化代码。

    【讨论】:

    • 还想补充一点,在控制器和服务之间使用静态类时,我遇到了升级到 MSDTC 的问题
    【解决方案3】:

    你需要有意识地处理你的 objectcontext 的范围,比如做一个Unit Of Work pattern

    除此之外,我确实认为你应该重新考虑做所有静态的事情,因为 womp 说你会得到非常高的耦合,并且很难测试,你可以通过使用国际奥委会容器。

    我可以这么说,我以前做过那种事把自己烧死了:)

    【讨论】:

      【解决方案4】:

      单例(和描述的静态类)是邪恶的,应该不惜一切代价避免,尤其是在 Web 应用中。

      【讨论】:

      • 我不同意这一点,辅助方法在静态时是理想的。事实上,一些最好的辅助方法对于 Web 使用是静态的。请求、Server.MapPath、文件/目录等...
      猜你喜欢
      • 2017-12-08
      • 1970-01-01
      • 2011-11-17
      • 2014-04-30
      • 2020-10-18
      • 1970-01-01
      • 1970-01-01
      • 2015-02-21
      • 2014-02-05
      相关资源
      最近更新 更多