事件接收器内的 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);
正如 MdMazzotti 指出的那样,在这种情况下您实际上需要处理网络,我将使用 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);
}