存储库是Singleton还是Static或者没有?

JGC*_*JGC 15 architecture asp.net database-design domain-driven-design

我有一个ASP.NET网站,它使用域驱动设计并使用存储库进行数据库操作.
我想知道singleton存储库和静态存储库以及简单的存储库类的优缺点是什么,它将在每次访问时都是新的?
更进一步,如果有人可以比较和指导我使用其中的哪一个,我将不胜感激.

ono*_*nof 16

静态和单例不是Repository模式的好解决方案.如果您的应用程序将来会使用2个或更多存储库,该怎么办?

IMO最好的解决方案是使用Dependency Injection容器并在需要它的类中注入您的IRepository接口.

我建议你阅读一本关于域驱动设计的好书和一本关于依赖注入的好书(比如Mark Seeman 在.NET中依赖注入).


使用单例和静态类,您的应用程序将无法扩展

你有两个单例存储库:

class Repository<TEntity> {

  static Repository<TEntity> Instance { get { ... /*using sql server*/ } }
}

class Repository2<TEntity> {

  static Repository2<TEntity> Instance { get { ... /*using WCF or XML or any else */ } }
}
Run Code Online (Sandbox Code Playgroud)

使用它们的服务必须具有对其中一个或两者的静态引用:

class OrderService {

    public void Save(Order order) { Repository<Order>.Instance.Insert(order); }
}
Run Code Online (Sandbox Code Playgroud)

如果存储库是静态引用的,如何使用Repository2保存订单

更好的解决方案是使用DI:

interface IRepository<TEntity> { ... }

class SqlRepository<TEntity> : IRepository<TEntity> { ....}

class OrderService {
    private readonly IRepository<TEntity> _repo;

    public OrderService(IRepository<TEntity> repo) { _repo = repo; }

    public void Save(Order order) { repo.Insert(order); }
}
Run Code Online (Sandbox Code Playgroud)


Moh*_*bed 7

不要使用静态或单例存储库,因为:

  • 它影响testablility,你不能在单元测试时模拟它.

  • 它会影响可扩展性,您不能创建多个具体实现,并且无法在不重新编译的情况下替换行为.

  • 它影响生命周期管理方面的可扩展性,不依赖于依赖注入框架来注入依赖关系和管理生命周期.

  • 它影响可维护性,它强制依赖于具体实现而不是抽象.

底线:D​​ONT使用静态或单例存储库

而是在域模型项目中创建存储库接口,并在具体的数据访问项目中实现这些接口,并使用依赖注入框架.


小智 6

我个人恭敬地不同意以前的答案。

我开发了多个网站(一个网站每月有 700 万次页面浏览),并且我的静态存储库从未遇到过任何问题。

我的静态存储库实现非常简单,只包含对象提供程序作为属性。单个存储库可以包含您需要的任意数量的提供程序。

然后,提供者负责管理数据库连接和事务。使用 TransactionScope,消费者可以管理事务或将其交给提供者。

每个提供程序都是使用单例模式开发的。

这样,我可以通过简单地调用这个来获取我的对象:

var myObj = MyRepository.MyProvider.GetMyObject(id);
Run Code Online (Sandbox Code Playgroud)

在任何时候,在我的应用程序的每个 Web 池中,每种类型都只有一个存储库和一个提供程序。根据您网站上同时拥有的用户数量,您可以设置多个网络池(但大多数情况下一个就足够了)。

我没有看到我的存储库/提供者消费者与我的存储库耦合的位置。事实上,我的提供者的实现完全是从它们中抽象出来的。当然,我的存储库返回的所有提供程序都是接口,我可以随时轻松更改它们的实现并将我的新 dll 推送到 Web 服务器上。如果我想创建一个具有相同界面的全新提供者,我只需在一个地方更改它:我的存储库。

这样,无需添加依赖注入或创建自己的 ControllerFactory(用于 MVC 项目)。

而且您仍然可以在控制器中使用干净的代码。每次请求页面时,您还将节省大量的存储库创建和销毁(通常在您的 ControllerFactory 中使用反射)。

如果您正在寻找可扩展的解决方案(如果您确实需要它,而在大多数情况下这并不是真正的问题),与依赖注入相比,我开发存储库的方式应该永远不会成为问题。


Dmi*_*try 5

没有单例存储库的两个SOLID原因:

  • 存储库的使用者将存储库的实现耦合在一起。这将负面影响可扩展性和可证明性。这是DIP违规。取决于抽象,而不取决于混凝土。

  • 存储库实现将不得不违反SRP,因为它很可能最终将管理ORM会话,数据库连接以及潜在的事务。它也必须确保线程安全,因为它可能可以在多个线程中使用。相反,应该将数据库连接(ORM会话)注入到存储库实现中,以便使用代码可以将多个存储库调用安排到事务中。

解决这两个问题的可能方法是构造函数注入