首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#实体框架内存使用率高,内存泄漏?

C#实体框架内存使用率高,内存泄漏?
EN

Stack Overflow用户
提问于 2014-11-13 11:50:26
回答 1查看 13K关注 0票数 6

我有一个使用实体框架6运行的小型MVC When应用程序。当启动应用程序时,浏览主页(例如。( www.mywebsite.dev)在我的开发上。机器,应用程序池启动,页面按预期加载。

这是一个事实,主页是相当轻量级的,只从数据库得到一些东西(2个菜单,2个段落和文本,以及一个有3-4个对象的集合)应用程序池已经超过200 MB (!)在刚刚加载主页一次之后..。

使用文章,我设法弄清楚了如何对管理内存进行分析,我还删除了一些阻止上下文处理的静态属性。DbContext禁用延迟加载,

代码语言:javascript
复制
public class MyContext: DbContext
    {
        private readonly Dictionary<Type, EntitySetBase> _mappingCache = new Dictionary<Type, EntitySetBase>();

        #region dbset properties
        //Membership sets
        public IDbSet<UserProfile> UserProfiles { get; set; }
        public IDbSet<Project> Project { get; set; }
        public IDbSet<Portfolio> Portfolio { get; set; }
        public IDbSet<Menu> Menu { get; set; }
        public IDbSet<MenuItem> MenuItem { get; set; }
        public IDbSet<Page> Page { get; set; }
        public IDbSet<Component> Component { get; set; }
        public IDbSet<ComponentType> ComponentType { get; set; }
        public IDbSet<BlogCategory> BlogCategory { get; set; }
        public IDbSet<Blog> Blog { get; set; }
        public IDbSet<Caroussel> Carousel { get; set; }
        public IDbSet<CarouselItem> CarouselItem { get; set; }
        public IDbSet<Redirect> Redirect { get; set; }
        public IDbSet<TextBlock> TextBlock { get; set; }
        public IDbSet<Image> Image { get; set; }
        public IDbSet<ImageContent> ImageContent { get; set; }
        #endregion

        /// <summary>
        /// The constructor, we provide the connectionstring to be used to it's base class.
        /// </summary>
        public MyContext() : base("name=MyConnectionstring")
        {
            //Disable lazy loading by default!
            Configuration.LazyLoadingEnabled = false;

            Database.SetInitializer<BorloContext>(null);
        }

        //SOME OTHER CODE
}

我仍然在内存中看到许多对象,我希望它们与实体框架的延迟加载有关。

我已经设置了几个层次的网站;

  1. 控制器-通常的东西
  2. 服务-建立一个在控制器中使用的使用语句。这些服务是一次性的,包含一个UnitOfWork。UnitOfWork在服务的构造函数中初始化,并在服务自身被释放时被释放。
  3. UnitOfWOrk -- UnitOfWork类包含一个只读私有变量,其中包含上下文,以及一组属性,这些属性实例化了T类型的泛型存储库。再次,UnitOfWork是一次性的,在调用Dispose方法时它会处理上下文。
  4. Generic匹配一个接口,接受DbContext的构造函数,并通过一个接口提供一组基本的方法。

下面是一个如何使用此方法的示例。

PartialController

代码语言:javascript
复制
public class PartialController : BaseController
    {
        //private readonly IGenericService<Menu> _menuService;
        //private readonly UnitOfWork _unitOfWork = new UnitOfWork();
        //private readonly MenuService _menuService;

        public PartialController()
        {
            //_menuService = new GenericService<Menu>();
            //_menuService = new MenuService();
        }

        /// <summary>
        /// Renders the mainmenu based on the correct systemname.
        /// </summary>
        [ChildActionOnly]
        public ActionResult MainMenu()
        {
            var viewModel = new MenuModel { MenuItems = new List<MenuItem>() };

            try
            {
                Menu menu;
                using (var service = ServiceFactory.GetMenuService())
                {
                    menu= service.GetBySystemName("MainMenu");
                }

                //Get the menuItems collection from somewhere
                if (menu.MenuItems != null && menu.MenuItems.Any())
                {
                    viewModel.MenuItems = menu.MenuItems.ToList();
                    return View(viewModel);
                }
            }
            catch (Exception exception)
            {
                //TODO: Make nice function of this and decide throwing or logging.
                if (exception.GetType().IsAssignableFrom(typeof(KeyNotFoundException)))
                {
                    throw;
                }
                else
                {
                    //TODO: Exception handling and logging
                    //TODO: If exception then redirect to 500-error page.
                }

            }

            return View(viewModel);
        }
    }

ServiceFactory

代码语言:javascript
复制
public class ServiceFactory
    {
        public static IService<Menu> GetMenuService()
        {
            return new MenuService();
        }
}

MenuService

代码语言:javascript
复制
public class MenuService : BaseService, IService<Menu>
{
private readonly UnitOfWork _unitOfWork;
private bool _disposed;

public MenuService()
{
    if (_unitOfWork == null)
    {
        _unitOfWork = new UnitOfWork();
    }
}

/// <summary>
/// Retrieves the menu by the provided systemname.
/// </summary>
/// <param name="systemName">The systemname of the menu.</param>
/// <returns>The menu if found. Otherwise null</returns>
public Menu GetBySystemName(string systemName)
{
    var menu = new Menu();

    if (String.IsNullOrWhiteSpace(systemName)) throw new ArgumentNullException("systemName","Parameter is required.");

    if (Cache.HasItem(systemName))
    {
        menu = Cache.GetItem(systemName) as Menu;
    }
    else
    {
        var retrievedMenu = _unitOfWork.MenuRepository.GetSingle(m => m.SystemName.Equals(systemName), "MenuItems,MenuItems.Page");

        if (retrievedMenu == null) return menu;

        try
        {
            var exp = GenericRepository<CORE.Entities.MenuItem>.IsPublished();
            var menuItems = (exp != null) ?
                retrievedMenu.MenuItems.AsQueryable().Where(exp).Select(MenuTranslator.Translate).OrderBy(mi => mi.SortOrder).ToList() :
                retrievedMenu.MenuItems.Select(MenuTranslator.Translate).OrderBy(mi => mi.SortOrder).ToList();

            menu.MenuItems = menuItems;
        }
        catch (Exception)
        {
            //TODO: Logging
        }

        Cache.AddItem(systemName, menu, CachePriority.Default, CacheDuration.Short);
    }

    return menu;
}

public IEnumerable<Menu> Get()
{
    throw new NotImplementedException();
}

~MenuService()
{
    Dispose(false);
}

protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        if (disposing)
        {
            _unitOfWork.Dispose();
        }
    }
    _disposed = true;
}

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

}

GenericRepository

代码语言:javascript
复制
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class, IEntityObject

{/使用的数据库上下文。/内部MyContext上下文;

代码语言:javascript
复制
/// <summary>
/// The loaded set of entities.
/// </summary>
internal DbSet<TEntity> DbSet;

/// <summary>
/// The constructor taking the databasecontext.
/// </summary>
/// <param name="context">The databasecontext to use.</param>
public GenericRepository(MyContext context)
{
    //Apply the context
    Context = context;

    //Set the entity type for the current dbset.
    DbSet = context.Set<TEntity>();
}
public IQueryable<TEntity> AsQueryable(bool publishedItemsOnly = true)
{
    if (!publishedItemsOnly) return DbSet;
    try
    {
        return DbSet.Where(IsPublished());
    }
    catch (Exception)
    {
        //TODO: Logging
    }

    return DbSet;
}

/// <summary>
/// Gets a list of items matching the specified filter, order by and included properties.
/// </summary>
/// <param name="filter">The filter to apply.</param>
/// <param name="includeProperties">The properties to include to apply eager loading.</param>
/// <param name="publishedItemsOnly">True if only publish and active items should be included, otherwise false.</param>
/// <returns>A collection of entities matching the condition.</returns>
public virtual IQueryable<TEntity> Get(Expression<Func<TEntity, bool>> filter, string includeProperties, bool publishedItemsOnly)
{
    var query = AsQueryable(publishedItemsOnly);

    if (filter != null)
    {
        query = query.Where(filter);
    }


    if (String.IsNullOrWhiteSpace(includeProperties))
        return query;

    //Include all properties to the dbset to enable eager loading.
    query = includeProperties.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, includeProperty) => current.Include(includeProperty));

    return query;
}

}

长话短说。在我的代码/情况下,什么可能会导致这样的问题:当仅仅加载主页时,使用的是惊人的200 MB或更多?我注意到的一件奇怪的事情是,在加载页面之前,在下面的示例中,内存从111 mb跃升到232 MB;

用dotMemory编辑来自跟踪的结果

在加载完主页后,在结果下面编辑2。主页现在是空的,在全局asax中只调用一个服务。我把页面打开了一段时间,然后刷新,导致了所有的高峰。

下面是一个更详细的结果,有很多字符串占用了大量的内存..?

编辑3与dotMemory不同的视图

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-11-16 10:24:45

所以,现在图像更清晰了。dotMemory显示,您的应用程序只需要9Mb的内存,我们可以在快照视图中看到这一点。内存流量视图也证实了这一点。~73 to从剖析开始分配,~65 to已被收集到快照#1点。

那么显示在实时数据图表上的总内存使用情况呢,很抱歉,我之前没有意识到,您的应用程序内存使用大部分是第0代堆。(而且我也错过了您的应用程序在这个屏幕上的快照块上只使用了8MB)。

GEN0堆大小显示可以在第0代中分配给的最大字节;不表示在第0代中分配的当前字节数。http://msdn.microsoft.com/en-us/library/x2tyfybc(v=vs.110).aspx

GEN0堆大小看起来异常大,但它是.net垃圾收集器的内部细节,它有权这样做。

我曾大胆地表示,您的应用程序在计算机上运行时具有大量的RAM和/或大CPU缓存。但是它也可以是ASP服务器实现的特殊方面。

结论--你的应用程序内存使用没有问题:)至少在加载主页时是这样的。

我建议看dotMemory视频教程,以便学习如何使用它。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26908257

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档