Skip to content

[Bug] 与动态代理使用时,因内部 DbContext 生命周期管理不当导致连接池耗尽 #163

Description

@sappmis

问题描述
当项目中使用 IServiceCollection.AddFxServices() 这类通过 Castle.DynamicProxy 为业务服务添加 AOP 支持的方法时,EFCore.Sharding 会导致数据库连接池迅速耗尽,最终抛出 System.InvalidOperationException: Timeout expired 异常。

环境

.NET 版本:.NET 6/8

EFCore.Sharding 版本:x.x.x

数据库:SQL Server

根本原因分析

生命周期冲突:EFCore.Sharding 框架内部疑似将 DbContext 注册或缓存为 Singleton 或长生命周期对象。当它被注入到 Scoped 的业务服务中时,由于生命周期不匹配,DbContext 无法在请求结束后被正确回收,导致连接泄漏。

代理加剧泄漏:项目使用了动态代理(AOP)为 Scoped 服务创建代理。如果代理工厂(如 ProxyGenerator)是 Singleton,它将长期持有 Scoped 服务的引用,进一步阻止了服务和 DbContext 被垃圾回收,使得连接泄漏问题迅速暴露。

验证证据:在移除动态代理的 AOP 功能后,问题消失,说明代理的介入是触发此 Bug 的必要条件。

建议修复方案

方案一(框架层面):审查框架内部所有 DbContext 实例的注册和缓存逻辑,确保其生命周期为 Scoped,并遵循 .NET Core DI 的最佳实践。

方案二(用户层面):在文档中增加说明,尤其是在推荐与 AOP 框架(如 Castle.DynamicProxy、Autofac 等)集成时,应特别注意不要将任何与数据库操作相关的服务注册为 Singleton。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions