Ruud van Falier
Ruud van Falier

Reputation: 8877

Glass context database null

I'm experiencing an issue with Glass Mapper in my current project that I haven't encountered before.

Directly after Sitecore has been initialized, the Database property in my GlassContext (ISitecoreContext) is null.

// After Sitecore initialization, sometimes the glass context database is not initialized yet.
if (this.glassContext == null || this.glassContext.Database == null)
{
    this.glassContext = DependencyInjection.Container.Resolve<ISitecoreContext>();

    // Now I have a valid this.glassContext.Database ...
}

When I ask my DI framework (Windsor, so Glass' default) for an instance, it returns me one with a valid Database property.
For the time-being I'm doing this check before retrieving any items and it only needs this check one time (after that it's good until the next initialization), but would really like to know what is causing this.

Probably interesting to know: all item requests (getting items, casting items, etc.) are done through one service which gets the ISitecoreContext initialized in its constructor.
The ItemService has lifetime Singleton, the ISitecoreContext has lifetime Transient

Upvotes: 2

Views: 1816

Answers (2)

Kevin Brechb&#252;hl
Kevin Brechb&#252;hl

Reputation: 4727

I think that your ItemService was first time injected before Sitecore has a valid context, therefore Glass also cannot be have a valid context (database). Because your ItemService has a Singleton lifetime, the constructor is only called once and also the resolving of ISitecoreContext is done once. This means, if your ItemService is resolved the first time before Sitecore has a valid context, then your glassContext will be null. After you manually set the glassContext property in the Singleton instance, the next time it won't be null (but maybe not valid because you are in another request).

I would suggest you setting both dependencies either to Transient or to PerWebRequest.

Upvotes: 2

Nat
Nat

Reputation: 19

As stated in other comments, sometimes this is due to not specifying an appropriate lifestyle. Transient may give you memory leaks if you do not find an appropriate way to Release it. I personally often use the NoTrackLifestyle that ships with Glass Mapper, since it behaves more like Transient from other containers.

There are also occasions where you can attempt to resolve the service too early, this in particular can happen when running in pipeline entries etc where the context has not yet been resolved for the request. In these instances you can use either a named instance where you specify the database and / or it's name as a dependency.

Bear in mind in all cases, the sitecore context / service by default relies on the CONTEXT database, if Sitecore hasn't resolved it yet - neither will glass have.

When using it with the new Glass Delegate functionality, I have found it necessary sometimes to rely on a factory implementation that delays the getting of the service, it's not perfect, but serves it's purpose since the fluent configuration often won't have a context available at the time of instantiation. By adding a small factory, it can be delayed until the delegate code is actually called.

public interface ISitecoreServiceFactory
{
    // Gets the Sitecore service from the container
    ISitecoreService GetService();
}

There are also instances sometimes with this when Glass is used in the creation of SPEAK / Sheer UI dialogs.

Upvotes: 0

Related Questions