代码之家  ›  专栏  ›  技术社区  ›  Mr. Flibble

Linq到SQL DataContext Windsor IoC内存泄漏问题

  •  4
  • Mr. Flibble  · 技术社区  · 15 年前

    我有一个ASP.NET MVC应用程序,它使用Castler Windsor IoC在每个web请求的基础上创建Linq2SQL数据上下文。

    由于某些我不完全理解的原因,每次创建一个新的datacontext(在每个web请求上),大约8k的内存被占用而没有释放,这不可避免地会导致OutOfMemory异常。

    如果我强制进行垃圾回收,内存释放正常。

     public class DataContextAccessor : IDataContextAccessor
     {
        private readonly DataContext dataContext;
        public DataContextAccessor(string connectionString)
        {
            dataContext = new DataContext(connectionString);           
        }
        public DataContext DataContext { get { return dataContext; } }
     }
    

    用于实例化此功能的Windsor IoC网络配置如下所示:

     <component id="DataContextAccessor"
                 service="DomainModel.Repositories.IDataContextAccessor, DomainModel"
                 type="DomainModel.Repositories.DataContextAccessor, DomainModel"
                 lifestyle="PerWebRequest">       
        <parameters>
          <connectionString>
            ...
          </connectionString>
        </parameters>
      </component>
    

    有人知道问题是什么,以及如何解决吗?

    4 回复  |  直到 14 年前
        1
  •  6
  •   queen3    15 年前

    L2S DataContext实现IDisposable。您的接口还必须实现它,并调用DataContext.Dispose(),以便Windsor知道有需要处置的资源。

    顺便提一下,请注意温莎/IDisposable问题: http://www.jeremyskinner.co.uk/2008/05/03/aspnet-mvc-controllers-windsor-and-idisposable/ http://www.nablasoft.com/Alkampfer/?p=105

        2
  •  4
  •   Krzysztof Kozmic    14 年前

    不,你的 DataContextAccessor 不需要执行 IDisposable . Windsor非常聪明,可以在不修改类的情况下处理这个问题。

    DataContext 确实实现了它,Windsor看到了它并注册了它以进行清理(调用 Dispose 方法)。

    你需要做的是打电话 container.Release 并传递您的根服务(可能是 DataContextAccessor 就你而言)。Windsor随后将发布它及其所有依赖项(它还将调用 处置 数据上下文

    如果您使用ASP.NET MVC,请考虑使用MVCCONTIB项目,该项目具有温莎集成,可以处理组件的发布。

        3
  •  3
  •   Community datashaman    7 年前

    据我所知, queen3 DataContextAccessor 类需要实现 IDisposable datacontext.Dispose() 从其 .Dispose() 方法(免责声明:我没有与温莎城堡合作过。)

    或者,我会做的是把你的 DataContextAccessor 变成 DataContextFactory ,它只创建 DataContext GetContext() )。然后您可以执行以下操作:

    using(DataContext context = myDataContextFactory.GetContext()) {
        // Do whatever you want with the context
    }
    // Context is disposed here
    

    How do you reconcile IDisposable and IoC?

        4
  •  1
  •   kenno    14 年前

    我认为@Krzysztof Komic是对的。。。你应该释放你从温莎得到的一切。

    温莎对于任何一个习惯于使用IDisposable的人来说都是相当陌生的。这种明显差异的原因在于组件生命周期的管理。如果您从Windsor获取一个IDisposable组件,您不知道该实例是配置为瞬态还是单例(当然,这可能会随着应用程序的发展而改变)。

    如果您处理了一个组件,但后来发现它是一个单例组件,那么其他一些客户机代码会想知道为什么它的组件突然出现故障!?!只有温莎能够为您做出处置决定。

    很好的博客帖子Krzysztof(不会让我发布链接!)

    在我们的应用程序中,除了几个单件外,所有的东西都是暂时的。Transient似乎是最简单的模型(只要每个人都理解您必须“释放而不是处置”)。如果您的测试中有一个模拟容器,您可以设置一个期望,即为您的模拟解决的每个组件调用Release,并且我还听说transient比其他模式有更少的性能问题(??)?这段代码当然更便于移植。

    最后但并非最不重要的一点是,如果您有内存泄漏,您需要了解GC没有收集到什么以及为什么没有收集到某些内容,请查看Tess Ferrandez在windbg上的fab教程系列 http://blogs.msdn.com/b/tess/archive/2008/04/03/net-debugging-demos-lab-7-memory-leak-review.aspx ... 罪犯可能在某个意想不到的地方!