Why is my WPF Treeview bound to LinqToSql classes, which are the core of memory?

I have a WPF application that stops after running out of memory ...
These are basically TreeView display nodes, which are instances of the Linq To Sql OR Generated class ICTemplates.Segment. There are about 20 tables indirectly linked through associations with this class in the OR designer.

<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; 

I added an explicit Child property to the segment class that is looking for another table with parent records.

 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; } } 

The rest is data binding in combination with data templates to display each segment as a set of user interface controls.

I am sure that children load on demand (when I expand the parent) based on the response time. When I expand a node with children of 70 , it takes some time before the children are loaded (task manager shows using Mem as 1000000K!). If I parse the next node with approximately 50 children, BOOM! OutOfMemoryException

I ran VS Profiler to dig deeper and here are the results

Dashboard Objects of Life Distribution

The top 3 are Action, DeferredSourceFactory.DeferredSource, and EntitySet (all .Net / LINQ classes). The only user classes are segment [] and the segment is included in # 9 and # 10.

I canโ€™t think of the persecution. What could be the reason?

0
profiling linq-to-sql wpf treeview
source share
4 answers

The problem is creating multiple S1DataContext objects as Sirocco . I tried using the instruction to forcefully remove Dispose and make it available for collection. However, this led to an ObjectDisposedException, which I cannot understand about.

  • The control jumps from a string specifying the DockPanel KeeperOfAllControls data context.
  • [External code] (displayed on the call stack)
  • Segment.Children.get (has a use block with dc)
  • Back in the line in step 1 ... ObjectDisposedException Linq query uses tblSegments, which is retrieved from the local S1DataContext instance

In any case, I assume that there is something that prevents the creation and deletion of multiple DataContexts. So, I tried Singleton DataContext .
And it works!

  • The TreeView control is significantly more responsive, each node I tried loading at most in 3-4 seconds.
  • I put GC.Collect (for verification) before each retrieval / search, and now memory usage stays between 200,000-300,000K.

The created OR.Data.Linq.DataContext does not disappear if it is not explicitly used (there is memory). Trying to get rid of it in my case, it didnโ€™t work out ... although both functions had their own usage blocks (without a common DataContext instance). Although I don't like singletones, I create a small internal tool for developers, and therefore, do not mind it now. None of the LinqToSql samples I saw on the Internet had Dispose credentials.

So, I think the problem has been fixed. Thanks to all the people who acted like more eyeballs to make this mistake petty.

0
source share

is it possible to use the DataContext environment?

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

Have you tried using sql profiler ? may shed light on this question.

+1
source share

Have you tried using a global DataContext instead of one for each element?

Creating an entire DataContext with its own query and results can cause memory bloat.

0
source share

I do not know the exact solution, but a new statement in the connection can cause this. Because a new object can be created for each relationship (but, as I mentioned, I do not know if this is correct).

Could you try:

 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; } } 
0
source share

All Articles