带有StructureMap(IoC)的IQueryable存储库 - 我如何实现IDisposable?

RPM*_*984 5 structuremap idisposable iqueryable repository objectcontext

如果我有以下存储库:

public IQueryable<User> Users()
{
   var db = new SqlDataContext();
   return db.Users;
}
Run Code Online (Sandbox Code Playgroud)

我知道只有在触发查询时才会打开连接:

public class ServiceLayer
{
   public IRepository repo;

   public ServiceLayer(IRepository injectedRepo)
   {
       this.repo = injectedRepo;
   }

   public List<User> GetUsers()
   {
       return repo.Users().ToList(); // connection opened, query fired, connection closed. (or is it??)
   }
}
Run Code Online (Sandbox Code Playgroud)

如果是这种情况,我还需要使我的Repository实现IDisposable吗?

Visual Studio Code Metrics当然认为我应该.

我正在使用IQueryable因为我将查询控制到我的服务层(过滤器,分页等),所以请不要就我使用它的事实进行架构讨论.

BTW - SqlDataContext是我的自定义类,它扩展了Entity Framework的ObjectContext类(所以我可以拥有POCO派对).

所以问题 - 我真的必须实现IDisposable吗?

如果是这样,我不知道这是如何可能的,因为每个方法共享相同的存储库实例.

编辑

我正在使用Depedency Injection(StructureMap)将具体的存储库注入服务层.这个模式跟随app堆栈 - 我正在使用ASP.NET MVC,并且具体服务被注入到控制器中.

换一种说法:

  1. 用户请求URL
  2. 创建控制器实例,该实例接收新的ServiceLayer实例,该实例是使用新的Repository实例创建的.
  3. 控制器调用服务上的方法(所有调用使用相同的Repository实例)
  4. 一旦请求被提供,控制器就消失了.

我正在使用混合模式将依赖项注入我的控制器,根据StructureMap文档,这些实例将存储在HttpContext.Current.Items中.

所以,我不能这样做:

   using (var repo = new Repository())
   {
      return repo.Users().ToList();
   }
Run Code Online (Sandbox Code Playgroud)

因为这违背了DI的全部要点.

RPM*_*984 2

编辑 - 从 Ayende Rahien 收到的建议

收到 Ayende Rahien(以 Rhino Mocks、Raven、Hibernating Rhinos 闻名)的电子邮件回复。

他是这样说的:

您的问题是您像这样初始化上下文: _genericSqlServerContext = new GenericSqlServerContext(new EntityConnection("name=EFProfDemoEntities"));

这意味着上下文不拥有实体连接,这意味着它不会释放它。一般来说,最好让上下文创建连接。您可以通过使用以下方法来做到这一点: _genericSqlServerContext = new GenericSqlServerContext("name=EFProfDemoEntities");

这绝对是有道理的——但是我认为处理 SqlServerContext 也会处理底层连接,我猜我错了。

不管怎样,这就是解决方案——现在一切都得到了妥善处理。

所以我不再需要在存储库上使用:

public ICollection<T> FindAll<T>(Expression<Func<T, bool>> predicate, int maxRows) where T : Foo
        {
            // dont need this anymore
            //using (var cr = ObjectFactory.GetInstance<IContentRepository>())
            return _fooRepository.Find().OfType<T>().Where(predicate).Take(maxRows).ToList();
Run Code Online (Sandbox Code Playgroud)

在我的基础存储库中,我实现了 IDisposable 并简单地执行以下操作:

Context.Dispose(); // Context is an instance of my custom sql context.
Run Code Online (Sandbox Code Playgroud)

希望能帮助其他人。