C# 当只有读取操作时,可以将DbContext作为单例注入吗?

C# 当只有读取操作时,可以将DbContext作为单例注入吗?,c#,.net,entity-framework,ef-core-3.1,C#,.net,Entity Framework,Ef Core 3.1,我知道DbContext不是线程安全的,而且DbContext缓存数据,当多个事务试图将自己的更改保存/提交到数据库时,可能会导致数据不一致。因此,强烈建议每个请求注入它()。但我遇到的情况是,只存在读取操作(在独立类库中),没有事务或创建/更新/删除操作。 我的问题是:在这种情况下,作为单例注入DbContext安全吗?实体框架开发人员明确表示DbContext对于在其上执行的任何操作都不是线程安全的,而不仅仅是写入(添加、保存更改等)操作,如果你不想有一天花上几天调试神秘的失败,你应该相信他

我知道
DbContext
不是线程安全的,而且
DbContext
缓存数据,当多个事务试图将自己的更改保存/提交到数据库时,可能会导致数据不一致。因此,强烈建议每个请求注入它()。但我遇到的情况是,只存在读取操作(在独立类库中),没有事务或创建/更新/删除操作。

我的问题是:在这种情况下,作为单例注入
DbContext
安全吗?

实体框架开发人员明确表示
DbContext
对于在其上执行的任何操作都不是线程安全的,而不仅仅是写入(添加、保存更改等)操作,如果你不想有一天花上几天调试神秘的失败,你应该相信他们

即使在读操作中,EF也可以在其内部结构上执行非线程安全的内存写操作,您无法确定它在任何给定情况下都不会执行该操作。例如,关于查询返回的结果集的处理:

如果查询是跟踪查询,EF将检查数据是否表示 实体已在上下文实例的更改跟踪器中

所以,若查询是跟踪查询,它将检查当前实例的变更跟踪器,该实例中已经存在的具有相同密钥的此类实体,这意味着若此类实体不存在,它将其放入变更跟踪器中。这是写操作,所以不安全

你可以说,那么我就用
AsNoTracking()
。但是还有一个问题,关于conncurrent
AsNoTracking
查询,EF甚至不允许您执行它们。图书馆维护人员说:

不可能同时使用相同的DbContext,而且不仅仅是 用于跟踪查询。具体地说,DbContext具有底层 数据库的数据库连接,不能同时使用。那里 发动机罩下的其他各种部件是否工作正常 支持多线程

然而,实例化几个DBContext并没有什么错 并对它们执行查询—无论是跟踪还是非跟踪。那个 应该让你有你想要的行为。如果你遇到任何 其他问题请毫不犹豫地发回


因此,有一些未记录的内部组件不是线程安全的,当从多个线程对
DbContext
执行任何操作时,您无法确定不会命中这些组件。

实体框架开发人员明确表示
DbContext
对于任何操作都不是线程安全的在它上执行,而不仅仅是写(添加、保存更改等)操作,如果您不想在某一天花费数天调试神秘的故障,那么您应该相信这些操作

即使在读操作中,EF也可以在其内部结构上执行非线程安全的内存写操作,您无法确定它在任何给定情况下都不会执行该操作。例如,关于查询返回的结果集的处理:

如果查询是跟踪查询,EF将检查数据是否表示 实体已在上下文实例的更改跟踪器中

所以,若查询是跟踪查询,它将检查当前实例的变更跟踪器,该实例中已经存在的具有相同密钥的此类实体,这意味着若此类实体不存在,它将其放入变更跟踪器中。这是写操作,所以不安全

你可以说,那么我就用
AsNoTracking()
。但是还有一个问题,关于conncurrent
AsNoTracking
查询,EF甚至不允许您执行它们。图书馆维护人员说:

不可能同时使用相同的DbContext,而且不仅仅是 用于跟踪查询。具体地说,DbContext具有底层 数据库的数据库连接,不能同时使用。那里 发动机罩下的其他各种部件是否工作正常 支持多线程

然而,实例化几个DBContext并没有什么错 并对它们执行查询—无论是跟踪还是非跟踪。那个 应该让你有你想要的行为。如果你遇到任何 其他问题请毫不犹豫地发回


因此,有一些未记录的内部组件不是线程安全的,当您从多个线程对
DbContext
执行任何操作时,您无法确定不会命中这些组件。

我的问题是:为什么?为什么不让依赖注入做它最擅长的事情,并且在相当长的一段时间内做得很好呢?您希望通过使用singleton获得什么?我想说不,因为虽然没有数据库写入,但EF本身在从数据库读取数据时会将数据写入其内部结构,谁知道在多线程处理时会发生什么行为,当库开发人员明确地告诉您库不是线程安全的时。@franzgleichman,因为1)每次调用该
dbContext
的方法时,我都会多次调用它,我需要使用(scope){create dbContext()}语句为每个方法添加
,这会污染代码。2) 每个方法都需要大量调用,每次调用实例化
DbContext
10次可能会使服务器崩溃(即使使用DbContextPool)。3) 你为什么不换个角度思考呢?在安全的情况下,为什么我们不将其作为一个单例注入(并切断所有与作用域
DbContext
)呢?@Evk“EF本身在从数据库读取数据时将数据写入其内部结构”您能给我一个提到的链接吗?不,但这只是常识。您自己说,
DbContext
缓存数据,这就是写操作(这意味着它将缓存的实体写入内部结构的某个位置,以便稍后返回)。还有很多问题