【问题标题】:What is the thread safety concern with singleton scope of the service class (and default scoped scope of dbcontext)?服务类的单例范围(以及 dbcontext 的默认范围)的线程安全问题是什么?
【发布时间】:2022-01-06 13:57:50
【问题描述】:

控制器方法调用此 ValidateUser 方法。例如验证用户。然后该服务调用 dbcontext。例如进行 db 查询。

什么范围(transient/scoped/singleton)适合服务类?

据我了解,假设如果范围设置为单例,那么在应用程序的整个生命周期中将只有 1 个此类实例。即使默认情况下 DbContext 是作用域的,在整个生命周期内(来自此服务类的实例)只会存在 1 个连接。

假设我设置为瞬态,那么对服务类的每个请求都会创建一个新的类实例。由于 dbcontext 是作用域的,因此它将是 1 个用户请求生命周期的 1 个实例。

假设我设置为作用域,那么每个用户对服务类的请求都会创建该类的新实例。由于 dbcontext 是作用域的,它将是 1 个用户请求生命周期的 1 个实例

什么是线程安全问题?

namespace MyApp.Services
{
    public class ValidateService : IValidateService
    {
    private readonly MyAppContext _context;

        public ValidateService(MyAppContext context)
        {
            _context = context;
        }

        public bool ValidateUser(UserDTO user)
        {
            return await _context.Users.AnyAsync(x => x.username == user.UserName);
        }
    }
}

【问题讨论】:

  • 我不知道,我认为它是 variab.. 哦
  • 顺便提一下,如果包含Service类的定义,这个问题可能会更好接受
  • 我请求重新打开这个问题。
  • 您是否在问“如果我将 Y 限定为 a) 瞬态,b) 限定范围并使 N Y的用途?”还是您在问“为什么 DbContext 不是线程安全的?”
  • 我已经给出了我对第 1 部分的理解 - 我的问题是第 2 部分 - 也就是说 - 为什么在单例的情况下 DbContext 不是线程安全的,以及在服务范围内它如何成为线程安全的类是作用域的或瞬态的。

标签: c# .net-6.0


【解决方案1】:

在依赖注入期间,DbContext 被初始化为一个对象池,每个请求都可以重用,因此 DbContext 的作用域生命周期可以利用这一点。至于与 dbcontext 一起使用的 Service 类,建议匹配现有对象的最短生命周期(在这种情况下,由于 dbcontext 的作用域)。

在以下链接中有更多信息。

https://codereview.stackexchange.com/questions/15703/threadsafe-dbcontext-in-singleton

https://stackoverflow.com/questions/37507691/entity-framework-core-service-default-lifetime

【讨论】:

  • 附加信息... 服务类中的单例不是线程安全的,每个 HTTP 请求都在不同的线程上运行。您会很快发现您的 DbContext 实例抛出与并发相关的异常。
  • 当我创建 builder.Services.AddDbContext 时,没有指定范围的选项
  • @eric - 我没有使用全局变量,为什么它不是线程安全的?
  • 单例实际上是一个全局变量。该类仅存在一个实例。
  • builder.Services.AddDbContext() 是一个带有可选参数的重载方法,Lifetime 就是这样一个可选参数,如果不提供则默认为作用域。
猜你喜欢
  • 2012-12-19
  • 2015-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 2017-04-10
  • 2014-03-28
  • 2012-05-04
相关资源
最近更新 更多