c# - 注入(inject)存储库上的 IDisposable

标签 c# ado.net dependency-injection 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.
   }
}

此存储库通过 IoC 容器注入(inject)域服务,并像这样使用:

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 语句中,这样当它完成时,连接就会关闭并被处理掉,但我认为这是一个问题,因为领域服务类仍然存在,如果有第二个调用它,它将失败,因为存储库已经被销毁。

现在我已经完全控制了所有代码,我只想设计粗粒度的服务调用,但总感觉有些不对劲。

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

这种设计本质上是不好的还是有更好的方法?

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

最佳答案

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

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

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();
      }
   }
}

您不必总是注入(inject)所需的类型。在阅读 CaSTLe Windsor(其思维方式是注册-解析-发布)时,您会发现如果您想在应用程序生命周期中的不确定时间解决问题,建议使用类型工厂。

您知道您将需要一个存储库,但不知道什么时候。与其请求存储库,不如请求能够创建它们的东西。因此保持了抽象级别,您没有泄漏任何实现。

关于c# - 注入(inject)存储库上的 IDisposable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9995877/

相关文章:

c# - 禁用 c# 控制台的最大化和最小化按钮

.net - 我可以为此使用 Entity Framework 吗?

c# - 如何使用标准 MVC Core 依赖注入(inject)解决未注册的类型

c# - 具有依赖注入(inject)的类单例行为

c# - 什么是 "Dispatcher"设计模式?

c# - 让单元测试循环运行是不好的做法吗?

c# - 违反 PRIMARY KEY 约束。无法在对象中插入重复的键

c# - ADO.NET 导航属性

java - Spring中如何从@Autowired List<>的每个bean中获取@Qualifier

c# - Alt+Numpad 键生成哪种编码?