C# 实体框架的这种实现是否会泄漏内存?

C# 实体框架的这种实现是否会泄漏内存?,c#,entity-framework-4,memory-leaks,idisposable,disposable,C#,Entity Framework 4,Memory Leaks,Idisposable,Disposable,当在web应用程序或控制台应用程序的using语句中使用实体上下文时,我就是搞不清楚它是否在使用流中被释放 谢谢 using System; using System.Web; namespace Foo.Model { public partial class FooEntities : ObjectContext { private const string CurrentContextKey = "FooEntities.Current";

当在web应用程序或控制台应用程序的using语句中使用实体上下文时,我就是搞不清楚它是否在使用流中被释放

谢谢

using System;
using System.Web;

namespace Foo.Model
{
    public partial class FooEntities : ObjectContext
    {
        private const string CurrentContextKey = "FooEntities.Current";

        [ThreadStatic]
        private static FooEntities _currentOnThreadStatic;
        private FooEntities _previousContext;

        /// <summary>
        /// Gets the current <see cref="FooEntities"/> instance, if an instance can be shared in the current context.
        /// </summary>
        /// <remarks>
        /// The current context is stored in the HTTP context, if it is available (otherwise it is stored in a thread-static instance).
        /// Multiple contexts can be stacked.
        /// </remarks>
        public static FooEntities Current
        {
            get
            {
                if (HttpContext.Current != null)
                {
                    return HttpContext.Current.Items[CurrentContextKey] as FooEntities;
                }
                else
                {
                    return _currentOnThreadStatic;
                }
            }

            private set
            {
                if (HttpContext.Current != null)
                {
                    HttpContext.Current.Items[CurrentContextKey] = value;
                }
                else
                {
                    _currentOnThreadStatic = value;
                }
            }
        }

        /// <summary>
        /// Returns a repository instance bound to this object context.
        /// </summary>
        /// <typeparam name="TRepository">The type of repository to instantiate.</typeparam>
        /// <returns>The repository instance.</returns>
        public TRepository GetRepository<TRepository>()
            where TRepository: BaseRepository
        {
            return (TRepository) Activator.CreateInstance(typeof(TRepository), this);
        }

        /// <summary>
        /// Ensures that an ambient context is available through <see cref="Current"/>, throwing an exception otherwise.
        /// </summary>
        /// <exception type="InvalidOperationException)">
        /// Thrown if <see cref="Current"/> is null.
        /// </exception>
        public static void EnsureContext()
        {
            if (Current == null)
            {
                throw new InvalidOperationException("An ambient FooEntities context is expected.");
            }
        }

        /// <summary>
        /// Releases the context instance.
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            Current = _previousContext;
            base.Dispose(disposing);
        }

        /// <summary>
        /// Is called by all constructors.
        /// </summary>
        partial void OnContextCreated()
        {
            _previousContext = Current;
            Current = this;
        }
    }
}
使用系统;
使用System.Web;
名称空间Foo.Model
{
公共部分类实体:ObjectContext
{
private const string CurrentContextKey=“FooEntities.Current”;
[线程静态]
私有静态实体\u currentOnThreadStatic;
私人实体(前文),;
/// 
///获取当前实例(如果实例可以在当前上下文中共享)。
/// 
/// 
///如果当前上下文可用,则将其存储在HTTP上下文中(否则将存储在线程静态实例中)。
///可以堆叠多个上下文。
/// 
公共静态实体当前
{
得到
{
if(HttpContext.Current!=null)
{
返回HttpContext.Current.Items[CurrentContextKey]作为FooEntities;
}
其他的
{
返回_currentOnThreadStatic;
}
}
专用设备
{
if(HttpContext.Current!=null)
{
HttpContext.Current.Items[CurrentContextKey]=值;
}
其他的
{
_currentOnThreadStatic=值;
}
}
}
/// 
///返回绑定到此对象上下文的存储库实例。
/// 
///要实例化的存储库的类型。
///存储库实例。
公共存储库GetRepository()
存放地点:BaseRepository
{
return(TRepository)Activator.CreateInstance(typeof(TRepository),this);
}
/// 
///确保环境上下文通过可用,否则将引发异常。
/// 
/// 
///如果为空,则抛出。
/// 
公共静态文本()
{
如果(当前==null)
{
抛出新的InvalidOperationException(“应为环境FooEntities上下文”);
}
}
/// 
///释放上下文实例。
/// 
/// 
受保护的覆盖无效处置(布尔处置)
{
当前=_先前的上下文;
基地。处置(处置);
}
/// 
///由所有构造函数调用。
/// 
部分无效OnContextCreated()
{
_previousContext=当前;
电流=这个;
}
}
}

这是一种奇怪的设计。正如@joelc在他的评论中指出的,您应该将对象上下文视为一个短暂的对象,在需要时创建它,然后立即释放


但我看不出这会泄露内存的原因。您只处理托管资源,并且始终使用相同的密钥访问
HttpContext
,因此不会创建新对象。

您有理由尝试在HttpContext中存储ObjectContext吗?上下文被认为是轻量级的,通常在需要时创建实例,然后处理掉它。因此,foodentities.Current可以用于在不同的类中插入实例,这样就不必在构造函数中注入实例,并在所有这些类中保持相同的实例。我认为您应该阅读这篇文章:这可能会促使您重新考虑线程静态上下文。@Ladislav Mrnka:我认为实现id是c*&p。我不支持它,也没有写它,也没有想象它。我认为实体上下文应该被注入到需要访问模型的类中,顶级请求处理程序应该实例化它。太难看了!总之,我同意你的观点,希望没有人把它作为做什么的例子,而是作为不做什么的例子。ObjectContext是IDisposable的,所以它不是托管资源。这就是我担心内存泄漏的原因。@Four:对不起,之前没有看到
OnContextCreated
,但我仍然认为这很好,因为保持链接列表活动的“锚”是
HttpContext
,它本身非常短暂。它更像一个内存“气球”,而不是内存泄漏。所有的东西最终都会被释放,所以从技术上讲这不是一个漏洞。但是,在最终处置之前加载到上下文中的实体越多,用于更改跟踪、跟踪关系等的内存就越多。@Anders实际上,终结器确保释放托管资源。如果您使用的是非托管资源,如句柄,您自己负责,如果不正确处理对象,将导致内存泄漏。但是,它最常用于托管资源,以确保及时处理事务,而不是等待GC,例如数据库连接。@Joel:如果遵循实现
IDiposable
的普通模式,终结器将调用
Dispose(false)
,这将释放所有非托管资源。
false
标志告诉
Dispose(bool disposing)
它应该忽略任何托管引用,只释放非托管资源。