统一处理数据库上下文的正确方法

Posted

技术标签:

【中文标题】统一处理数据库上下文的正确方法【英文标题】:Proper way of dispose a database context with unity 【发布时间】:2021-12-10 16:35:14 【问题描述】:

我正在使用统一和依赖注入,目前,我对连接的处理有点困惑。

我会举一个例子,希望我能正确解释:)

我有一个使用服务的控制器:

public class CompaniesController : IDatabaseController
    
        private readonly ICompaniesService _companiesService;
        public CompaniesController(ICompaniesService companiesService)
        
         _companiesService = companiesService;
        
    

服务注册到 UnityConfig 为:

container.RegisterType<ICompaniesService, CompaniesService>(new HierarchicalLifetimeManager());

*** 我读到如果我使用 IDisposable,那么 HierarchicalLifetimeManager 是强制性的。

实现接口的服务(我知道也可以注入数据库连接,但超出问题范围的原因请忽略)是这样的:

public class CompaniesService : ICompaniesService
    
        private readonly DatabaseContext _db = Helpers.GetDatabaseContextForRequest();

        /// <summary>
        /// Returns all employee of a company
        /// </summary>
        /// <param name="company_id">The id of the company</param>
        /// <returns>A collection of EmployeeDAP</returns>
        public IEnumerable<EmployeeDAP> GetCompanyEmployees(int company_id)
        
            var employees = CompaniesRepository.GetCompanyEmployees(company_id);
            return employees;
        

问题来了。 我应该也实现服务的 IDisposable 接口并处理数据库连接,还是 GC 来清理混乱?

如果我必须手动处理连接,我应该使用 Dispose Pattern 还是

public void Dispose()
        
            ((IDisposable)_db).Dispose();
        

够了吗?

提前致谢

更新:

辅助方法如下:

try
            
                DatabaseContext db = (DatabaseContext)getRequestValue(name);
                if (db == null || !db.Database.Exists())
                
                    db = new DatabaseContext();
                    setDatabaseContextForRequest(db, name);
                
                return db;
            
            catch (Exception)
            
                return new DatabaseContext();
            

其中新的 DatabaseContext 继承自 EF 的 DbContext。

【问题讨论】:

你能展示一下Helpers.GetDatabaseContextForRequest() 的作用吗?因为如果它返回并持有一个DatabaseContext作为请求的范围,并且你一个接一个地调用多个服务,你可能会过早地处理DatabaseContext。似乎您在 Helpers 内有一个隐藏范围,可能在 DI 容器中显式。 @Gwinn,该方法并不像您自己看到的那样花哨。它只是创建一个新的数据库上下文以防它不存在。 【参考方案1】:

我认为让服务来处理DatabaseContext 是给服务过多的责任。

我会将 DatabaseContext 配置从 Helpers 类移动到 Unity,使用 PerRequestLifetimeManager 注册它。 使用 Unity 作为生命周期管理器,您将获得跨越 HTTP 请求的 DatabaseContext,将 HTTP 请求的生命周期近似为 DatabaseContext 的生命周期。

这种方法将允许您避免让服务拥有 DatabaseContext 生命周期的所有权,将所有清理逻辑和所有权保留在 Unity 容器中。此外,您将能够在单个请求中在服务之间安全地共享 DatabaseContext 实例,因为 DatabaseContext 仅在请求结束时被释放。

最后,请记住,一旦您丢弃了某些东西,您将无法再次使用它,因此您必须改进 Helpers.GetDatabaseContextForRequest() 以重新创建 DatabaseContext(如果已丢弃)。

【讨论】:

以上是关于统一处理数据库上下文的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

SpringMVC统一异常处理(返回异常数据而不是跳转到某个页面的方法)

Web API统一异常处理 转载

spring boot 2 全局统一返回RESTful风格数据统一异常处理

统一异常处理

自定义参数校验以及统一处理结果集

django基础——上下文处理器