Reputation: 8877
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
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
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