November Happy Hour will be moved to Thursday December 5th.

Cascading Deletes of Categories

Vote:
 

I am working on a task where I need to trigger an update to a third party whenever a category is deleted.  I have the event handler for the delete coded to handle this, but it doesn't seem to handle any child categories (or dedescents) when performing this delete.  Is there a way of generating the cascaded delete other than manually looping through all the descendents of a category and deleting them out one by one in a recursive format?  I am using commerce v. 10.3

#176614
Mar 23, 2017 1:28
Vote:
 

Hi Steven

We have had some performance issues deleting CatalogNodes, and we have found out that there are different ways of deleting them.

Could you share some code showing how you try to delete the categories?

We are using the ICatalogSystem.DeleteCatalogNodesAndEntries() method to delete the CatalogNodes. We tried using the ICatalogSystem.DeleteCatalogNode metod as well. That also seems to work, but it does a lot of in-memory work with the catalog structure, and in our case where we needed to delete a large number of CatalogNodes durin our catalog import, this gave us major performance issues. DeleteCatalogNodesAndEntries() uses stored procedures to delete the data. The method name also suggests that it may delete CatalogEntries as well as nodes. In our case that is not an issue, because we have already removed any relevant CatalogEntries from the catalog structure before we do the deletion (we do the work during catalog import).

If you are using the Content API instead, the code above may not be relevant for you.

Regards

Anders Kåre Olsen

#176620
Mar 23, 2017 8:16
Vote:
 

It can be a pretty tricky, as if you receive the event after the node is deleted, then it's impossible to call DeleteCatalogNodesAndEntries(). If you can listen to Deleting event, aka before the node is deleted, then it's an option.

Another option is to listen to RelationDeleted event. From the event you can get the CatalogRelationDto (cast source object), get the NodeEntryRelation, then get the entry ids and delete them.

#176621
Mar 23, 2017 9:00
Vote:
 

I am using the content api.  What I have today is on the deleting content event, I execute an extension function on the ContentRepository class that deletes the children of the current node for a specific type.  

      private static void DeletingCategoryNode(object sender, DeleteContentEventArgs eventArgs)
        {
            var content = eventArgs.Content as CategoryNode;
            //how to recursively delete category?
            if (content != null)
            {
                //delete child category    
                var contentRepo = ServiceLocator.Current.GetInstance<IContentRepository>();
                contentRepo.DeleteChildren<CategoryNode>(content.ContentLink);
            }
        }
       public static void DeleteChildren<T>(this IContentRepository contentRepository, ContentReference contentLink) where T : class, IContent
        {
            var children = contentRepository.GetDescendents(contentLink);
            foreach (var childRef in children)
            {
                var child = contentRepository.Get<T>(childRef);
                if (child != null)
                {
                    contentRepository.Delete(child.ContentLink, false);
                }
            }
        }
#176686
Mar 23, 2017 15:40
Vote:
 

I've been advocating the uses of Content APIs - but this is the place where ICatalogSystem.DeleteCatalogNodesAndEntries works better. Use ReferenceConverter.GetObjectId(nodeContentLink) to get the node id and pass to that method, and you're good to go

#176687
Mar 23, 2017 15:56
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.