让存储库手动打开和关闭数据库连接是不是一种糟糕的做法
本文关键字:一种 是不是 数据库连接 存储 | 更新日期: 2023-09-27 18:24:15
环境:ASP.NET MVC3 C#
假设我有一些存储库(semi-psuedo):
public interface IRepository
{
create();read();update();delete();opendb();closedb();
}
public class CarRepository : IRepository
{
private DbContext namedDbContext;
public void opendb()
{
namedDbContext = new DbContext();
}
public void closedb()
{
namedDbContext.dispose();
}
}
然后在控制器中,存储库被注入并按如下方式用于手动控制数据库连接寿命:
public class SomeController : Controller
{
private IRepository CarRepository;
public void SomeController(IRepository _carRepository)
{
CarRepository = _carRepository;
}
public ActionResult SomeAction(int CarId)
{
CarRepository.opendb();
var car = CarRepository.read(CarId);
CarRepository.closedb();
}
}
这是否被认为是一种糟糕的做法,因为它从存储库中获取连接的控制权并将其放置在控制器中?我担心使用依赖项注入会导致内存泄漏,并希望确保不会打开重复的连接,也不会长时间运行和未使用。
是。当然大多数ADO.NET驱动程序都使用连接池,因此实际的连接过程并没有那么繁重。您有TransactionScope
,它可以处理多个连接上的事务,但它不会像一个连接上一个事务那样快。
我担心使用依赖项注入会导致内存泄漏,并希望确保不会打开重复的连接,也不会长时间运行和未使用。
IoC将保证清理连接(大量用户已经确保了这一点)。不能保证程序员会在所有地方进行清理。
假设模式提供了持久层的抽象。它不应该公开任何持久性细节,比如数据库连接。如果存储是xml文件或云存储,该怎么办?
所以,是的,这是一种糟糕的做法。如果你想要更多的控制,你可以让存储库使用工作单元模式,这样更高的级别应该决定何时提交事务,但仅此而已。存储库不应该公开数据库的任何信息。
至于内存泄漏,请使存储库隐含IDispable(关闭任何未完成的打开连接),并确保DI容器管理每个请求的存储库实例,它将对其调用Dispose。
存储库的一部分是抽象持久性的细节。
我看到你的提议有两个问题:
- 通过将这些方法命名为"opendb"answers"closedb"和
- 如果按此路线进行,则应该从
opendb()
方法返回IDisposable
(连接对象),并将该操作封装在using
块中,以确保连接关闭
通常,您可以让存储库为每个方法创建一个连接,所以您只需要在存储库方法中正确地进行连接。当您想要对存储库执行多个操作,而不需要对每个部分使用单独的连接时,就会遇到挑战。
为了实现这一点,您可以从存储库中公开工作单元的概念。您的工作单元将实现存储库方法的接口,因此您不能在工作单元之外调用它们。它还将实现IDisposable
,因此无论何时调用存储库,都将使用using
块。在内部,存储库将管理连接,但既不会公开连接,也不会"谈论它"
例如:
public ActionResult SomeAction(int CarId)
{
using (var repo = CarRepository.BeginUnitOfWork())
{
var car = repo.read(CarId);
// do something meaningful with the car, do more with the repo, etc.
}
}