10

在我的 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 问题?

4

4 回答 4

16

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

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

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

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

于 2010-02-17T19:46:06.787 回答
10

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

于 2010-02-17T19:45:07.553 回答
1

您需要以一种深思熟虑的方式处理对象上下文的范围,例如执行工作单元模式

除此之外,我确实认为你应该重新考虑做所有静态的事情,因为 womp 说你会得到非常高的耦合,并且很难测试,并且你可以通过使用 IOC 容器来管理依赖关系图获得很多帮助。

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

于 2010-02-17T20:03:05.687 回答
-4

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

于 2010-02-17T20:09:50.990 回答