为什么我的WPF Treeview绑定到LinqToSql类是一个记忆猪?

时间:2009-01-08 11:57:09

标签: wpf linq-to-sql treeview profiling

我有一个WPF应用程序,在内存耗尽后停止运行...
它基本上是一个显示节点的TreeView,它们是Linq To Sql OR Generated类ICTemplates.Segment的实例。在OR设计器中,大约有20个表通过关联间接链接到此类。

<TreeView Grid.Column="0" x:Name="tvwSegments" 
                      ItemsSource="{Binding}" 
                      SelectedItemChanged="OnNewSegmentSelected"/>
<HierarchicalDataTemplate DataType="{x:Type local:Segment}" ItemsSource="{Binding Path=Children}"> 
...

// code behind, set the data context based on user-input (Site, Id)
KeeperOfControls.DataContext = from segment in tblSegments
   where segment.site == iTemplateSite && segment.id == iTemplateSid
   select segment;

我在segment类中添加了一个名为Children的显式属性,该类查找具有父子记录的另一个表。

public IEnumerable<Segment> Children
{
  get
  {
    System1ConfigDataContext dc = new System1ConfigDataContext();
    return from link in this.ChildLinks
      join segment in dc.Segments on new { Site = link.ChildSite, ID = link.ChildSID } equals new { Site = segment.site, ID = segment.id }
      select segment;
  }
}

其余部分是数据绑定与数据模板相结合,以将每个Segment显示为一组UI控件。

我非常肯定孩子们按照响应时间按需加载(当我扩展父级时)。当我使用 70 子项扩展节点时,在加载子项之前需要一段时间(任务管理器将Mem Usage显示为1000000K!)。如果我用大约50个孩子扩展下一个节点,那么BOOM! OutOfMemoryException异常

我运行VS Profiler深入挖掘,结果如下

Summary Page Object Lifetimes Allocation

前3个是Action,DeferredSourceFactory.DeferredSource和EntitySet(所有.Net / LINQ类)。唯一的用户类是Segment [],Segment来自#9和#10。

我想不出要追求的原因......可能是什么原因?

4 个答案:

答案 0 :(得分:1)

可能是围绕DataContext使用吗?

using(System1ConfigDataContext dc = new System1ConfigDataContext()){
  .... ?
}

另外,您是否尝试使用sql profiler?可能会对此事有所了解。

答案 1 :(得分:0)

您是否尝试过为每个元素使用全局DataContext而不是一个?

使用自己的查询创建所有DataContext,结果可能是导致内存膨胀的原因。

答案 2 :(得分:0)

我不知道确切的解决方案但是联接中的新语句可能会导致这种情况。因为对于每个关系都可以创建一个新对象(但正如我所提到的,我不知道它是否正确)。

你能试试吗;

public IEnumerable<Segment> Children
{
  get
  {
    System1ConfigDataContext dc = new System1ConfigDataContext();
    return from link in this.ChildLinks
      join segment in dc.Segments on link.ChildSite == segment.site && link.ChildSID == segment.id
      select segment;
  }
}

答案 3 :(得分:0)

问题似乎是创建多个S1DataContext对象,因为 Sirocco 被引用。 我尝试使用using语句强制Dispose并使其符合收集条件。但是它导致了一个我无法理解的ObjectDisposedException。

  1. 控件来自设置DockPanel KeeperOfAllControls的数据上下文的行。
  2. [外部代码](显示在调用堆栈中)
  3. Segment.Children.get(有一个带dc的使用块)
  4. 返回步骤1中的行... ObjectDisposedException Linq查询使用从S1DataContext的本地实例检索的tblSegments
  5. 无论如何,我认为有些东西会阻止创建和处理多个DataContexts。所以我尝试了Singleton DataContext 它的工作原理!

    • TreeView控件的响应速度要快得多,我试过的每个节点最多加载3-4秒。
    • 我在每次获取/搜索之前输入了GC.Collect(用于验证),现在内存使用率保持在200,000-300,000K之间。

    OR生成的System.Data.Linq.DataContext似乎没有消失,除非它被明确处理(吃掉内存)。尝试在我的情况下处理它,没有平移..即使两个函数都有自己的使用块(没有DataContext的共享实例)。虽然我不喜欢Singletons,但我正在为开发人员制作一个小型内部工具,因此现在不介意它。我在网上看到的所有LinqToSql样本都没有。已经强制要求Dispose。

    所以我猜这个问题已得到修复。感谢所有能够使这个问题更加浅薄的人们。