Parallel foreach issue while deleting a record - Front- & Back-End Development - Front- & Back-End Development - Progress Community
 Front- & Back-End Development

Parallel foreach issue while deleting a record

  • Parallel foreach issue while deleting a record
  • Hi,

    Please find below code where I am trying to acheive parallel deleting of all products in sitefinity. Looks like there is a scoping issue. 

       using (CatalogManager catMgr = CatalogManager.GetManager())
               
                    List<Product> products = catMgr.GetProducts().ToList();

                    Parallel.ForEach(products, product =>
                        catMgr.DeleteProduct(product);
                        catMgr.SaveChanges();
                    );                 
                 

     

    This code gives the error <b>Object references between two different object scopes are not allowed. The object 'Telerik.Sitefinity.DynamicTypes.Model.sf_ec_prdct_generalproduct' is already managed by 'ObjectScopeImpl 0x38 OpenAccessRuntime.EnlistableObjectScope' and was tried to be managed again by 'ObjectScopeImpl 0xfd OpenAccessRuntime.EnlistableObjectScope'.</b>

    Please let me know in case I am missing something.

    Thanks

    Praneeth

  • Hi Praneeth,

    The error is caused by the fact that the manager did not save changes between two different operations, thus the managers works in different scope, which is not allowed.

    More information about deletion of Products could be found here.

    Regards,
    Svetoslav Manchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  • Thank you for your reply. Please let me know in case there is any alternative to parallely delete multiple records. I cannot rely on one by one delete as I have approximately 200,000 records and it is taking a very lot of time.

    Thanks
    Praneeth

  • Hello Praneeth,

    As the parallel items deletion is not allowed, the option for is to get all the Items (Products) in a batches (for example by 500), iterate in a loop and delete them one by one. Than to call manager.SaveChanges() after each batch.

    Regards,
    Svetoslav Manchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  • Anything similar to insert multiple users/products/orders. Please note all are new users/products/orders.

    This task is for migrating from existing ecomm database to sitefinity database.

     Thanks,
    Praneeth

  • Hello Praneeth,

    More information and samples about eCommerce API is available in that documentation.

    How to manage users programatically is described here.

    Regards,
    Svetoslav Manchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  • Hello Svetoslav,

     Based on the suggestion I did write the code in batches but it still seem to be slow. I tried batches of 10. Please find my codesnippet below. catalogmanager.SaveChanges() for 10 products takes a long time. Please check and let me know in case I missed anything.

     

     private void DeleteProducts(DynamicModuleManager dynamicModuleManager, DynamicContent content, IEnumerable<ProductImportCSV> products)
       
            try
           
                DynamicContent dynamicItemMaster = dynamicModuleManager.Lifecycle.Edit(content) as DynamicContent;

                if (dynamicItemMaster == null)
               
                    throw new ApplicationException("DeleteProducts Product Dynamic Item Master was null!");
               

                DynamicContent dynamicItemTemp = dynamicModuleManager.Lifecycle.CheckOut(dynamicItemMaster) as DynamicContent;

                if (dynamicItemTemp == null)
               
                    throw new ApplicationException("DeleteProducts Product Dynamic Item Temp was null!");
               

                dynamicItemTemp.SetValue(BatchUploadConstants.JobStatus, ProductBatchUploadStatus.Deleting.ToString());

                PublishDynamicModule(dynamicModuleManager, dynamicItemTemp);
                Guid vendorid = content.GetValue<Guid>(BatchUploadConstants.VendorId);

                using (CatalogManager catalogManager = CatalogManager.GetManager())
               
                    catalogManager.Provider.SuppressSecurityChecks = true;

                    IEnumerable<ProductImportCSV> productImportCsvs = products as IList<ProductImportCSV> ?? products.ToList();
                    // ignore empty records. most likely issue with csv
                    productImportCsvs = productImportCsvs.Where(p => !string.IsNullOrEmpty(p.SKU));
                    IQueryable<Product> masterProducts = catalogManager.GetProducts().Where(p => p.Status == ContentLifecycleStatus.Master );

                    var deleteMasterProducts = Enumerable.Where(masterProducts, p => p.GetValue<TrackedList<Guid>>(DynamicProductConstants.Category).Contains(vendorid));
     
                      // Run in batches
                    int skip = 0;
                    int take = _batchSize == 0 ? 10 : _batchSize;
                    int currentCount = 0;

                    int totalCount = deleteMasterProducts.Count();
                    while (currentCount < totalCount)
                   
                        string skusNotDeleted = string.Empty;
                        try
                       
                           var chunkedProducts = deleteMasterProducts.Skip(skip).Take(take);
                            skip = skip + take;
                            currentCount = skip;

                            foreach (Product product in chunkedProducts)
                           
                                if (string.IsNullOrEmpty(product.Sku))
                               
                                    continue;
                               

                                skusNotDeleted += product.Sku + " ,";
                                catalogManager.DeleteProduct(product);
                               
                           

                            catalogManager.Provider.FlushTransaction();
                            catalogManager.SaveChanges();
                            GC.Collect();
                       
                        catch
                            _errorLog.Append(" SKUs not deleted are : " + skusNotDeleted + ". ");
                       
                                    

               
           
            catch (Exception ex)
           
                _errorLog.Append("Error occurred while deleting and exception message is : " + ex.Message + " " + Environment.NewLine);
           
       

  • Hello Praneeth,

    The code seems OK. Furthermore I have test product deletion of 12 products using the following code:
    public static void DeleteProducts()
        CatalogManager catalogManager = CatalogManager.GetManager();
     
        var products = catalogManager.GetProducts();
     
        foreach (var product in products)
        
            catalogManager.DeleteItem(product, null);
        
        catalogManager.SaveChanges();

    and SaveChanges() takes just few (2-3) seconds. I would recommend you to open a support ticket in order to provide us with your project and to inspect the issue locally.

    Regards,
    Svetoslav Manchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  • Hi Murli,

    Thank you for the shared solution with the community.

    Regards,
    Svetoslav Manchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  • To delete the records i have used below code.

    I have created the records using the dynamic module and wanted to delete all old records so i have write the code like below. may be this code helpful to other

    public static void DeleteAllUnclaimedDividendRecords()
           
                DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager();
                Type unclaimedDividendType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.UnclaimedDividend.UnclaimedDividend");
                var myCollection = dynamicModuleManager.GetDataItems(unclaimedDividendType);
                foreach (var item in myCollection)
               
                    dynamicModuleManager.DeleteItem(item);
               
                dynamicModuleManager.SaveChanges();
           

    Thanks,

    Murli