统一处理数据库上下文的正确方法
Proper way of dispose a database context with unity
我正在使用统一和依赖注入,目前,我对连接的处理有点困惑。
我举个例子希望我解释正确:)
我有一个使用服务的控制器:
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 来清理混乱?
如果我必须手动处理连接,我应该使用处理模式还是
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();
}
其中new DatabaseContext继承自EF的DbContext。
我认为提供服务来处理 DatabaseContext
给了服务太多的责任。
我会将 DatabaseContext
配置从 Helpers
class 移动到 Unity,使用 PerRequestLifetimeManager
.
注册它
使用 Unity 作为生命周期管理器,您将获得跨越 HTTP 请求的 DatabaseContext
,使 HTTP 请求生命周期近似于 DatabaseContext
.
的生命周期
这种方法将允许您避免让服务获得 DatabaseContext
生命周期的所有权,将所有清理逻辑和所有权保留在 Unity 容器中。此外,您将能够在单个请求中的服务之间安全地共享 DatabaseContext
实例,因为 DatabaseContext
仅在请求结束时处理。
最后,请记住,一旦您处置了某些东西,您将无法再次使用它,因此您必须改进 Helpers.GetDatabaseContextForRequest()
以在处置后重新创建 DatabaseContext
。
我正在使用统一和依赖注入,目前,我对连接的处理有点困惑。
我举个例子希望我解释正确:)
我有一个使用服务的控制器:
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 来清理混乱?
如果我必须手动处理连接,我应该使用处理模式还是
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();
}
其中new DatabaseContext继承自EF的DbContext。
我认为提供服务来处理 DatabaseContext
给了服务太多的责任。
我会将 DatabaseContext
配置从 Helpers
class 移动到 Unity,使用 PerRequestLifetimeManager
.
注册它
使用 Unity 作为生命周期管理器,您将获得跨越 HTTP 请求的 DatabaseContext
,使 HTTP 请求生命周期近似于 DatabaseContext
.
这种方法将允许您避免让服务获得 DatabaseContext
生命周期的所有权,将所有清理逻辑和所有权保留在 Unity 容器中。此外,您将能够在单个请求中的服务之间安全地共享 DatabaseContext
实例,因为 DatabaseContext
仅在请求结束时处理。
最后,请记住,一旦您处置了某些东西,您将无法再次使用它,因此您必须改进 Helpers.GetDatabaseContextForRequest()
以在处置后重新创建 DatabaseContext
。