SP ProcessBatchData внутри приемника событий, проблема с низкой производительностью
-
10-12-2019 - |
Вопрос
Я пишу приемник событий в библиотеке документов, чтобы создать новый список из загруженного файла Excel.он запускается при событиях ItemAdded() и ItemUpdated().
Прежде чем вызвать метод для добавления новых элементов в список, мне нужно очистить старые элементы. Сначала я попробовал это традиционным способом (итерация в порядке убывания и удаление всех записей), а теперь с помощью Процессбатчдата
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 немного лучше, но все еще неточно, проблема в том, что во время отладки, как только элемент управления достигает линии var deleteBatch = site.OpenWeb().ProcessBatchData(BuildBatchDeleteCommand(site.OpenWeb().Lists[listName]));
Он возвращает управление на экран загрузки документа и в большинстве случаев не затрагивает оставшийся код. Однако, если количество записей действительно мало (<100), он обрабатывает и переносит управление на следующую строку ( InsertIntoList(ExcelRecords, site.OpenWeb().Lists[listName].Items);
).
Не могу выяснить, является ли это проблемой потока. Если я сделаю эту работу, я переведу поток в спящий режим на некоторое время, пока ProcessBatch не завершит свою работу и управление не перейдет к следующей строке.
Полная функция выглядит так
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);
}
}
}
});
}
Ребята, пожалуйста, укажите мне правильное направление.Я очень ценю вашу помощь и время.
Вишал
Решение
Вероятно, это не основная причина ваших проблем с производительностью, а ее часть.Ваш код написан совершенно неэффективно: он открывает веб-страницы справа и слева и ищет список несколько раз.Что-то вроде этого делает то же самое, но более эффективно:
Если ваша функция доступна в Интернете:
var web = properties.Feature.Parent as SPWeb;
если область действия сайта ограничена
var site = properties.Feature.Parent as SPSite;
if(site == null) return;
var web = site.OpenWeb(properties.WebUrl);
и, как отметил МдМаццотти, в этом сценарии вам действительно потребуется удалить сеть, я бы использовал оператор using, заменив последнюю строку следующим:
using(var web = site.OpenWeb(properties.WebUrl)){
и добавить доп. }
В конце следующего:
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);
}