注入存储库上的IDisposable

我有以下ADO .Net存储库

public class Repository : IRepository, IDisposable { private readonly IUnitOfWork UnitOfWork; private SqlConnection Connection; public Repository(IUnitOfWork unitOfWork, connectionString) { UnitOfWork = unitOfWork; Connection = new SqlConnection(connectionString); Connection.Open(); } public MyObject FindBy(string userName) { //...Ado .Net command.ExecuteReader, etc. } } 

此存储库向IOS容器注入域服务,使用方式如下:

 public class UserDomainService : IUserDomainService { private readonly IRepository Repository; public UserDomainService(IRepository repository) { Repository = repository; } public User CreateNewUser(User user) { using(Repository) { var user = Repository.FindBy(user.UserName); if(user != null) throw new Exception("User name already exists!"); Repository.Add(user); Repository.Commit(); } } } 

我的想法是我总是将Repository对象放在using语句中,所以当它完成时,连接被关闭并处理掉,但是我认为它是一个问题,因为Domain Service类仍然存在并且如果有第二次调用它,它将失败,因为存储库已被销毁。

现在我可以完全控制所有代码,我只想设计粗粒度服务调用,但是有一些东西感觉不对。

我这样做是因为我可以避免域服务知道存储库中的OpenConnection和CloseConnection方法。

这种设计本质上是坏的还是有更好的方法来做到这一点?

经过深思熟虑 :当请求到达时,所有依赖树都是在WCF级别生成的,当然你可以看到连接是在那一刻打开的,因为它发生在存储库的构造函数中,所以我相信它不是那么糟糕,因为它仅在此特定呼叫期间开放。 我是正确的这个假设还是我在这个过程的早期打开数据库连接做了一件非常糟糕的事情?

注入一个工厂,创建您需要的实例,而不是实例本身。

获取一个IRepositoryFactory以便您可以创建一个IRepository并在每次使用它时将其处理IRepository 。 这样,域服务或工厂都不需要是一次性的。 此外,重要的是,通过仍然注入实现而不是硬编码来保持代码抽象。

 public class UserDomainService : IUserDomainService { private readonly IRepositoryFactory RepositoryFactory; public UserDomainService(IRepositoryFactory factory) { RepositoryFactory = factory; } public User CreateNewUser(User user) { using (IRepository repository = RepositoryFactory.Create()) { var user = repository.FindBy(user.UserName); if(user != null) throw new Exception("User name already exists!"); repository.Add(user); repository.Commit(); } } } 

您并不总是需要注入所需的类型。 在阅读Castle Windsor(其心态是注册 – 解析 – 释放)时,您会发现如果您想在应用程序生命周期的不确定时间解析内容,建议使用Type Factories。

你知道你需要一个存储库,但不知道什么时候 。 而不是要求存储库,而是要求创建它们的东西。 因此保持了抽象级别,并且您没有泄露任何实现。

你遇到的问题是所有权问题。 UserDomainService类不创建IRepository ,但它仍然拥有该实例的所有权,因为它处理它。

一般规则是创建对象的人应该破坏它。 换句话说,创建对象的人是所有者,所有者将销毁该对象。

您的问题有两种解决方案。

  1. 正如亚当清楚解释的那样,创建一个IRepositoryFactory 。 这样的工厂上的CreateNewRepository()方法将清楚地传达调用者获得所有权并应该处置该创建的存储库。

  2. 让创建(并注入)该存储库的人处理该存储库的处理。 您可以在WCF服务中手动执行此操作,也可以使用IoC / DI框架。 如果您使用DI框架,您应该查看每Web请求生命周期或类似的内容。

最后请注意,您的IRepository实现了IDisposable 。 在选择解决方案2时,您可以从IRepository删除IDisposable接口,这隐藏了应用程序涉及资源的事实。 从应用程序隐藏IDisposable是一件好事,因为该接口是一个漏洞的抽象。 您已经遇到过此问题,因为从应用程序中调用Dispose会破坏整个应用程序。