Skip to content
March 19, 2014 / kiranpatils

Cannot access a disposed object. Object name: ‘LuceneSearchContext’.

Challenge:

Yes, I am enjoying working on latest Search API, So, as you?! But while working on it faced following challenge:

System.ObjectDisposedException: Cannot access a disposed object. Object name: ‘LuceneSearchContext’. at Sitecore.ContentSearch.LuceneProvider.LuceneSearchContext.get_Searcher() at Sitecore.ContentSearch.LuceneProvider.LinqToLuceneIndex`1.ExecuteQueryAgainstLucene(LuceneQuery query) at Sitecore.ContentSearch.LuceneProvider.LinqToLuceneIndex`1.FindElements[TElement](LuceneQuery query) at Sitecore.ContentSearch.Linq.Parsing.GenericQueryable`2.GetEnumerator() at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext() at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)

So, as you? Don’t worry it’s good to face challenge(s), Remember :

A challenge only becomes an obstacle when you bow to it.Ā -Ray Davis

So, If you are facing this error, Or working with Search API and would like to sharpen your weapons to kill this error, whenever it appears before you then my dear soldier this post is for you!

Solution:

Before we come to solution, let’s see how we faced this error.We believe that

To fix any error, you should know how to reproduce it!

So, let’s see How I met this error! šŸ™‚

Following method helps us to find an item(s) from bucket using StartSearchLocation (If you are new to StartSearchLocation then I would must recommend you to read this blog :Ā  http://www.sitecore.net/Community/Technical-Blogs/Sitecore-7-Development-Team/Posts/2013/10/Using-the-new-Sitecore-7-Field-Types.aspx) :

private IEnumerable FindItemFromBucket(string importValue,
StringComparison stringComparisonType, string startSearchLocation,
string filterByFieldName)
{
IEnumerable<Item> items = null;

ISearchIndex searchIndex = ContentSearchManager.Indexes.FirstOrDefault(x => x.Name == "sitecore_master_index");

using (var context = searchIndex.CreateSearchContext())
{

items = LinqHelper.CreateQuery(context,
UIFilterHelpers.ParseDatasourceString(startSearchLocation)).Select(x => x.GetItem())
.AsEnumerable()
.Where(x => x.Language == Sitecore.Context.Language)
.Where(resultItem => resultItem[filterByFieldName].Equals(importValue,
stringComparisonType));

return items;
}

}

The method looks easy, Correct? But

Life is not as easy as it seems to be!

And when we call this method using following way:

string StartSearchLocation = "StartSearchLocation={4346502C-1315-4647-82C4-7B38301A7493}&TemplateFilter={4AB443DE-4444-4A2A-ACE4-E53635E05324}|{C068356E-192F-4D5A-ADA6-8F7250A24A3E}|_path:{4346502C-1315-4647-82C4-7B38301A7493}";
IEnumerable foundItems = null;
foundItems = FindItemFromBucket("VALUE", StringComparison.InvariantCultureIgnoreCase, StartSearchLocation, "MYFIELD");

//if you find one then store the id
if (foundItems.Any())
{
gvResults.DataSource = foundItems;
gvResults.DataBind();

}

When we ran it, we faced above given error. Then we asked to our common friend – Google! And yes you said right — It never disappoints us!

http://stackoverflow.com/questions/21827441/sitecore-7-search-cannot-access-a-disposed-object
“It seems that SearchResults<T> holds reference to SearchHit and the LuceneSearchProvider doesn’t hold a reader open. The new version of Lucene automatically closes the reader. I think you might be returning the wrong type. You should probably do like this:”

Basically, While returning results from your method rather than returning SearchResults<T> type of object. Better to return List. Tried it and it worked! So, here’s the final method:

private IEnumerable FindItemFromBucket(string importValue,
StringComparison stringComparisonType, string startSearchLocation,
string filterByFieldName)
{
IEnumerable<Item> items = null;

ISearchIndex searchIndex = ContentSearchManager.Indexes.FirstOrDefault(x => x.Name == "sitecore_master_index");

using (var context = searchIndex.CreateSearchContext())
{

items = LinqHelper.CreateQuery(context,
UIFilterHelpers.ParseDatasourceString(startSearchLocation)).Select(x => x.GetItem())
.AsEnumerable()
.Where(x => x.Language == Sitecore.Context.Language)
.Where(resultItem => resultItem[filterByFieldName].Equals(importValue,
stringComparisonType));

return items.ToList();

}

}

That’s it!

Happy Sitecore Searching! šŸ™‚

Good reads:

http://patrickdelancy.com/2013/09/filtering-sitecore-7-multilist-search-treelist-search/#.UyiPLIX3NtY

http://www.nonlinearcreations.com/Digital/how-we-think/articles/2014/03/4-patterns-Sitecore-component-development.aspx

PS : Special thanks to my colleagues Dan and Marcia who helped me to understand Search API basics, and helping me wherever I got stuck!

Advertisements

3 Comments

Leave a Comment
  1. Nick Wesselman (@techphoria414) / Mar 19 2014 12:30 am

    Yeah the issue here is the delayed execution of the LINQ query. By calling ToList(), you are forcing execution of the query before you close the search context. If you want to retain the delayed execution, the Sitecore 7 Dev Team has a good post about this.

    http://www.sitecore.net/Community/Technical-Blogs/Sitecore-7-Development-Team/Posts/2013/04/Sitecore-7-Patterns-for-Global-Search-Context-Reuse.aspx

    Though their idea of opening a search context across the whole Application makes me a little nervous!

    -Nick

    • kiranpatils / Mar 19 2014 12:40 am

      Nick,

      Thank you for sharing your thoughts!

      Yeah, I had a read to this post earlier. But thanks for sharing! Yeap, using Application context worried me as well. I liked this approach and I was looking for a quick and easy way as the functionality which I was working was not expecting delayed execution.

      So, In summary for a quick way is to use ToList approach. But the recommended approach is the way Sitecore team suggested in article.

      Keep reading!

      Kiran

  2. Golden grahams / Apr 19 2014 3:44 am

    Glad my stackoverflow question helped.

    There was an issue with the lucene provider, the code worked great with the solr provider. If you really need to return the GetResults() method, you can get round the issue by setting a singleton style search context- sounds daunting but it does work.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: