Question

I am writing an Event Receiver on a Document Library to create a new list from the uploaded excel file. it runs on ItemAdded() and ItemUpdated() event.

Before calling a method to add new Items to List I need to clear old Items, I initially tried this with the traditional way (iterating in descending order and delete all records) and now with the ProcessBatchData

 using (SPSite site = new SPSite(properties.WebUrl))
                        {
                            if (site.OpenWeb().Lists[listName].Items.Count > 0)
                            {
                                var deleteBatch = site.OpenWeb().ProcessBatchData(BuildBatchDeleteCommand(site.OpenWeb().Lists[listName]));
                            }
                            InsertIntoList(ExcelRecords, site.OpenWeb().Lists[listName].Items);
                        }

ProcessBatachData is some what better but still not accurate the issue is that while debuggin once the control reaches the line var deleteBatch = site.OpenWeb().ProcessBatchData(BuildBatchDeleteCommand(site.OpenWeb().Lists[listName]));

It takes the control back to the document upload screen and most of the times doesn't hit the remaining code, However if records are really low ( < 100) then it process and takes the control to the next line ( InsertIntoList(ExcelRecords, site.OpenWeb().Lists[listName].Items); ).

Not able to figure out if its an thread issue, If I make this work my putting thread to sleep for sometime until the ProcessBatch finishes its job and control move to next line.

The complete function looks like

 public override void ItemUpdated(SPItemEventProperties properties)
        {
            UpdateMarketingCalendar(properties);
            base.ItemUpdated(properties);
        }


private void UpdateMarketingCalendar(SPItemEventProperties properties)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                try
                {
                    using (SPSite site = new SPSite(properties.WebUrl))
                    {
                        SPList list = site.OpenWeb().Lists[listName];

                        bool recordsRetrieved;
                        DataTable ExcelRecords = GetRecordsFromExcel(properties.ListItem, out recordsRetrieved);

                        if (recordsRetrieved)
                        {
                            if (list.ItemCount > 0)
                            {
                                var deleteBatch = site.OpenWeb().ProcessBatchData(BuildBatchDeleteCommand(list));
                            }
                            InsertIntoList(ExcelRecords, list.Items);
                        }
                    }
                }

            });
        }

Geeks please point me to the right direction. I really appreciate you help and time.

Vishal

Was it helpful?

Solution

This is probably not the root cause of your performance issues, but part of it. Your code is written in a quite inefficient way, opening webs to the right and left and looking for the list multiple times. Something like this does the same thing but more efficiently:

If your feature is web scoped:

    var web = properties.Feature.Parent as SPWeb;

if site scoped

    var site = properties.Feature.Parent as SPSite;
    if(site == null) return;
    var web = site.OpenWeb(properties.WebUrl);

and as MdMazzotti pointed out you would actually need to dispose the web in this scenario, I would use the using statement, replace the last line with this:

using(var web = site.OpenWeb(properties.WebUrl)){

and add an extra } at the end of the following :

    if(web == null || !web.Exists) return;

    var list = web.Lists[listName]
    if (list != null && list.Items.Count > 0)
    {
        var deleteBatch = web.ProcessBatchData(BuildBatchDeleteCommand(list));
    }

    InsertIntoList(ExcelRecords, list.Items);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top