Don’t dispose your Dynamic Data Store Factory

DynamicDataStoreFactory.Instance is by default implemented by EPiServerDynamicDataStoreFactory. This class implements IDisposable and if you call dispose on this class you will notice that you application starts giving a lot of null reference exceptions when trying to get stores. But I’m getting ahead of myself, let’s start with a very important question.

Why would you dispose your dynamic data store factory?

Ah yea, this was a very subtle issue that occurred in connection to my IoC-container of choice, StructureMap. I started to get the null reference error on a schedule job. The weird thing was that the job worked the first time it executed but would fail on all the following runs. When I rebuilt the site the job worked again the first time and then failed. I had the following pieces.

The scheduled job

public RgsNotificationSenderJob(IChangesToRgsFeedsService changesToRgsFeedsService)
{
    if (changesToRgsFeedsService == null) throw new ArgumentNullException("changesToRgsFeedsService");
    _changesToRgsFeedsService = changesToRgsFeedsService;
}

The service

The service the job takes as a constructor argument has the following contructor.

public ChangesToRgsFeedsService(DynamicDataStoreFactory dataStoreFactory)
{
    _dataStoreFactory = dataStoreFactory;
    _dataStore = _dataStoreFactory.GetStore(typeof(RgsFeedRemovedPage));
}

The IoC registration

The instance to use for DynamicDataStoreFactory is registered as follows

For<DynamicDataStoreFactory>().Use(() => DynamicDataStoreFactory.Instance);

When all the planets align…

After some digging around the IoC-container setup I noticed that all the scheduled jobs were run in a nested container. There is a very important piece of how a nested container treats transient objects, it will call dispose on all of them when you dispose the nested container. The running of the jobs looked something like this

using (var nestedContainer = Container.GetNestedContainer(profile))
{
    // get and run job
}

Since it’s in a using statement it will call dispose on our instance of DynamicDataStoreFactory because it’s created in the nested container (since we use the func syntax “() =>” for a reason that doesn’t matter here). The important thing here is that since DynamicDataStoreFactory.Instance is a singleton it should also be registered as such. The nested container will not dispose singeltons or any other objects it has not created it self.

For<DynamicDataStoreFactory>().Singleton().Use(() => DynamicDataStoreFactory.Instance);

Thanks to Joel and Patrik for both mental and technical support during the ride.

  • http://twitter.com/bjuris Per Bjurström

    Kind of tricky, you would think that lifetime is not managed by StructureMap when you provide the instance yourself. We started using nested containers in older hybrid tests so I spent a few hours tracking down the same problem, I had to download the source code for StructureMap to figure it out. Thanks for sharing this, hopefully it helps someone.