5

I have some "caching" objects in my application, that get a IRepository (custom repository pattern contract) by dependency injection (Ninject). Those objects only uses the repository once, but they have a Refresh function that forces the owner to refresh itself. They are singletons, are created only once, and a ManualResetEvent ensures that all requests are blocked till it is loaded.

The IRepositories are EF CodeFirst based, so is it OK just to simply ensure the connection is closed and keep the reference to the DbContext there forever?

I have disabled the proxies and the lazy loading, so... is OK to have long references from the root of the caching object to hundreds of these cached POCO entities?

Cheers.

vtortola
  • 34,709
  • 29
  • 161
  • 263

2 Answers2

2

We reference to comments from Julie Lerman, http://msdn.microsoft.com/en-us/magazine/ee532098.aspx?sdmr=JulieLerman the recommendation is to have several/many smaller contexts and in the case of web scenarios create a new context each call. Although she writes about Second-Level Caching in the Entity Framework and AppFabric.

Over time, the context would be contain many objects and the performance would decline accordingly. I think this site has some good tips on EF performance. eg generated views. http://msdn.microsoft.com/en-us/data/hh949853

my personal recommendation, that I cant claim is best practice, but from someone who is concerned about performance, is that small bounded context each call is a solid long term compromise. Use generated views to keep the initial load time as small as possible.

you could potentially manage a permanent DBContext in such a way as to drop unused objects from the context. Or use a caching library with events to do so. Not a small task.

I would be interested in the solution you finally select. please post.

phil soady
  • 11,043
  • 5
  • 50
  • 95
0

Finally the best solution I found is to create a new kind of wrapper:

    public class Generator<T> where T : IDisposable
    {
        readonly Func<T> _generate;
        public Generator(Func<T> generate)
        {
            _generate= generate;
        }

        public T Generate()
        {
            return _generate();
        }
    }

And create a binding more or less this way:

// Dependency Injection bindings declaration section
DI.Bind<Generator<IRepository>>()
  .To(()=> new Generator<IRepository>(()=> DI.Get<IRepository>()));

Therefore, in long lived objects that needs to just create and destroy the element, I can ask for a Generator<IRepository> service, rather than IRepository. Therefore, every time I need to refresh, I would just create a new IRepository, without knowing how it is build under the hood:

 using (var repository = repositoryGenerator.Generate())
 {
     repository.DoStuff();
 }

It works like a charm so far.

Actually, I have added this feature to my DI framework. I can now bind IAnything and later on request for Generator, and the framework will give me the fully ready object using this technique How to create a Func<> delegate programmatically

Cheers.

Community
  • 1
  • 1
vtortola
  • 34,709
  • 29
  • 161
  • 263