4

I know that when I edit items, I can pass true to the EndEdit method to save the item without triggering events/indexing on save. Since I almost always want to edit an item after creating it, it seems silly to me that my item should be indexed twice. How can I make it so that the item is only indexed once, after saving?

2 Answers 2

9

If you decompile and have a look at the Sitecore.Data.Items.ItemEditing class, in Sitecore.Kernel, you will find that all the EndEdit(bool) method does (and the relevant parts of its overload methods do) is essentially wrap the the call to ItemManager.SaveItem with an EventDisabler.

Solution 1:

To apply the same technique in order to make sure that your new item only indexes once for the entire creation and editing process, instead once for creation and once for editing, you could do the following:

using (new EventDisabler()) 
{
    var newItem = parent.Add(name, templateId);
}

newItem.Editing.BeginEdit();
newItem.Fields["Foo"].Value = fooFieldValue;
newItem.Editing.EndEdit();

The problem with this solution, however, is that it will disable all events on create, not just indexing events. What if you have item:created or item:added events?

Solution 2:

An an alternative, you could do the following:

IndexCustodian.PauseIndexing();
var newItem = parent.Add(name, templateId);
IndexCustodian.ResumeIndexing();

newItem.Editing.BeginEdit();
newItem.Fields["Foo"].Value = fooFieldValue;
newItem.Editing.EndEdit();

The problem here is that when you call PauseIndexing you are actually pausing indexing for the entire site. Sure, you're doing it for a very short amount of time, but you are still setting yourself up for failure.

Solution 3:

Another alternative is to try something like the following:

using (new BulkUpdateContext()) 
{
    var newItem = parent.Add(name, templateId);

    newItem.Editing.BeginEdit();
    newItem.Fields["Foo"].Value = fooFieldValue;
    newItem.Editing.EndEdit();
}

This should do what you are looking for, except that it won't work as expected if you want to add child/descendant items to your item or one of its descendants (if adding from a branch template) in the same closure. By example, the following will not work as expected, because the parent, newItem, for the childItem won't be available when the childItem is added:

using (new BulkUpdateContext()) 
{
    var newItem = parent.Add(name, templateId);

    newItem.Editing.BeginEdit();
    newItem.Fields["Foo"].Value = fooFieldValue;
    newItem.Editing.EndEdit();

    var newChildItem = newItem.Add(childName, childTemplateId);
    ...
}

Conclusion:

Unfortunately, I don't think there is a way to temporarily disable indexing for a particular item or for an item creation without using one of the above. Hopefully, one of them will fit your needs.

3
  • 1
    I'm curious why you say the parent newitem will not be available in the same closure? To my knowledge the .EndEdit() commits the change. BulkUpdateContext() is always the best approach IMO. While this is particularly good for large transactions, it will work just as well with one. When BulkUpdateContext() expires you can then issue a refresh on your newly created item per this blog post: link. Pay particular attention to the loop through indexes.
    – jrap
    Commented Oct 19, 2016 at 18:21
  • I have had numerous issues using BulkUpdateContext for creating data in hierarchies. Most recently, (and in 8.1.2) I tried to use it for bulk uploading items into a folder structure and attempted to use the Database.CreateItemPath method. The result was that the items were added, but under the root of the item path that I created. I saw a blog post online on this, as well, but I can't seem to find it now. If this was a bug or is not expected behavior, please let me know! I would love it if that were the case! Commented Oct 19, 2016 at 20:33
  • I just tried the exact test on an 8.1 v.151207 instance and it worked correctly. Code. Result. In my mind, BulkUpdateContext() is always the way to go. Note: The SecurityDisabler() was only added for simple testing.
    – jrap
    Commented Oct 20, 2016 at 18:02
-1

Have you tried to pause indexing for the time of creating and editing item operation? Something like this one:

try    
{
  Sitecore.ContentSearch.Maintenance.IndexCustodian.PauseIndexing();
  // your code here
}
finally
{
  Sitecore.ContentSearch.Maintenance.IndexCustodian.ResumeIndexing()
}

Sitecore might have some logic for analyzing and optimizing data to be indexed.

4
  • Be aware, that PauseIndexing() will pause indexing for the entire site, and should be used with caution. This approach is prone to errors.
    – Kasper
    Commented Oct 18, 2016 at 6:28
  • In case we know the specific index we can pause it by ISerchIndex.PauseIndexing(). However, in most cases, nobody knows which indexes should be paused. Commented Oct 18, 2016 at 7:16
  • Still, you would pause indexing globally (for that specific index).
    – Kasper
    Commented Oct 18, 2016 at 7:30
  • This was the same as my Solution 2, but I did describe the caveat of it pausing indexing for the whole site. I also did my best to mitigate it by only calling Add between these two calls. I'm sorry, but I just don't see what new information is gained from this solution. Commented Oct 18, 2016 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.