EF 6 Connection pool and stored query strings RAM leak

c# entity-framework entity-framework-6 oracle wpf

Question

I have 2 problems.

First one is that Connection pool and (OracleConnectionImpl) is growing steadily over time, till it reaches out of memory exception. As you can see on the image, it has 90 MB over 3-4 hours of running.

I am using short lived contexts everywhere, but it keeps on growing and never clears itself. Is there any way for me to clear it?

Second one is that EF stores too much duplicates of string queries over time. It mostly stores those which come from .Reload() function, because it is not paramterized, it hardcode the ID into the query. And then there are strings like "ID" which is somewhere cached 2947x.

Is there any way for the .Reload() function to make it parametrized, or to clear all of those stored strings?

This app is refreshing warehouse jobs and palletes every few seconds, to keep it in sync for all machines and I am not aware of better way than .Reload() because of WPF bindings.

dotMemory Snapshot

String duplicates

Edit 1

I have simple helper function for reloading many intities at once, even one extension. It doesnt matter that it is passed as object, because the same problem remains even with the last example.

     public static void ReloadEntities(bool dispatch, params IEnumerable<object>[] entities)
        {
            using (var ctx = new eWMSEntities())
            {
                if (dispatch)
                {
                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
                    {
                        entities.SelectMany(x => x.Select(s => s)).ToList().ForEach(entity =>
                       {
                           ctx.Set(entity.GetType()).Attach(entity);
                           ctx.Entry(entity).Reload();
                           ctx.Entry(entity).State = EntityState.Detached;
                       });
                    }, null);
                }
                else
                {
                    entities.SelectMany(x => x.Select(s => s)).ToList().ForEach(entity =>
                    {
                        ctx.Set(entity.GetType()).Attach(entity);
                        ctx.Entry(entity).Reload();
                        ctx.Entry(entity).State = EntityState.Detached;
                    });
                }
                ctx.Dispose();
            }
        }

        public static void ReloadEntity(this object entity, bool dispatch)
        {
            using (var ctx = new eWMSEntities())
            {
                ctx.Set(entity.GetType()).Attach(entity);
                if (dispatch)
                {
                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
                    {
                        ctx.Entry(entity).Reload();
                    }, null);
                }
                else
                {
                    ctx.Entry(entity).Reload();
                }
                ctx.Entry(entity).State = EntityState.Detached;
                ctx.Dispose();
            }
        }
    while (true && JobLines.Contains(line))
            {
                using (var ctx = new eWMSEntities())
                {
                    ctx.T_JOB_LINES.attach(line);
                    ctx.entry(line).Reload();
                }
await Task.Delay(3000);
            }

This is snapshot after 3 days of running Snapshot

1
4
3/23/2020 2:29:41 PM

Popular Answer

Use the "Unit of work" pattern - it will solve many problems. I did not find for WPF, but found for ASP.NET MVC

0
3/30/2020 11:37:59 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow