为什么使用 AddScoped() 而不是 AddSingleton()?

Why use AddScoped() instead of AddSingleton()?

为什么我应该为我的存储库或服务使用 AddScoped()?为什么不 AddSingleton()? 我知道它们之间的区别,但不明白为什么我不应该使用单例实例来避免为每个请求创建新对象。 你能解释一下吗(最好有例子:))?

以下三种方法定义了服务的生命周期,

  1. 添加瞬态 每次请求时都会创建瞬态生命周期服务。此生命周期最适用于轻量级、无状态服务。

  2. AddScoped 每个请求创建一次范围内的生命周期服务。

  3. AddSingleton 单例生命周期服务在第一次被请求时创建(或者当 ConfigureServices 为 运行 时,如果您在那里指定一个实例),然后每个后续请求都将使用相同的实例。

Reference here

假设您有一个 aspnet-core 项目。

  • 如果您只想在程序的运行时间内创建一个对象并且每次都使用同一个对象,您应该使用addingingleton。

  • 如果你想让一个对象在程序运行ning期间每次收到请求时都重新new(),你应该使用addscoped()。

  • 如果你想让一个对象在每次请求和响应时都new(),你必须使用AddTransient。

Example value of 3 methods

Understanding with an infographic

正如你所说,你知道其中的区别,所以我不会深入讨论。

您不想为您的存储库或服务添加 Singleton 的原因是,通常您的存储库和服务被视为“业务逻辑”和“持久性逻辑”。在您的业务逻辑中,您可能有一些正在设置的 class 级变量。这些属性对于每个请求都不会不同,它们将在请求之间共享。 (将它们视为静态属性)。

示例:

假设您有一个用户服务,它将发出请求的用户的用户名设置为 class 级别变量。

单例逻辑:

现在假设 Bob 向 api 发出请求。用户名将设置为 "Bob" 。现在想象一下,在同一时间,John 向 api 发出请求。用户名将设置为“John”。但是因为用户服务是单例的,所以 John 和 Bob 共享同一个实例,这意味着 Bob 的用户名也将设置为“John”。

作用域逻辑:

想象一下与上面完全相同的场景,但是这次当 John 发出请求时,它不会覆盖 bobs 用户名,因为它们是不同的实例。