批量获取函数结果
Get result from function in batches
我有一个函数可以从 SharePoint 列表中获取 x 个项目。它分批获取项目。在每批之后我对物品做一些事情,销毁所有东西并拿下一批进行计算。我目前考虑使用事件。所以每批都有一个事件。这是正确的策略还是有更好的方法?我在考虑匿名函数或类似的东西?
public static List<Item> GetAllItems(this List list, int rowLimit, List<string> fields, bool includeRoleAssignments, ILogger logger)
{
var result = new List<Item>();
var ctx = list.Context;
ListItemCollectionPosition position = null;
var camlQuery = new CamlQuery();
camlQuery.ViewXml =
@"<View Scope='RecursiveAll'>
<Query>
<OrderBy Override='TRUE'><FieldRef Name='ID'/></OrderBy>
</Query>
<ViewFields></ViewFields>" +
"<RowLimit Paged='TRUE'>" + rowLimit + "</RowLimit>" +
"</View>";
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
do
{
try
{
using (var clonedCtx = ctx.Clone(ctx.Url))
{
List listWithClonedContext = clonedCtx.Web.Lists.GetByTitle(list.Title);
clonedCtx.Load(listWithClonedContext);
clonedCtx.ExecuteQuery();
ListItemCollection listItems = null;
camlQuery.ListItemCollectionPosition = position;
listItems = listWithClonedContext.GetItems(camlQuery);
foreach (string field in fields)
{
clonedCtx.Load(listItems, includes => includes.Include(i => i[field]));
}
if (!includeRoleAssignments) {
clonedCtx.Load(listItems, item => item.ListItemCollectionPosition);
}
else {
clonedCtx.Load(listItems, item =>
item.ListItemCollectionPosition,
item => item.Include(
i => i.RoleAssignments.Include(
ra => ra.Member,
ra => ra.Member.LoginName,
ra => ra.RoleDefinitionBindings.Include(rd => rd.Description, rd => rd.Name))));
}
clonedCtx.Load(listItems, item => item.ListItemCollectionPosition);
clonedCtx.ExecuteQueryWithIncrementalRetry(3, 1, logger);
// here i want to do something with items before next loop/batch
position = listItems.ListItemCollectionPosition;
if (position != null)
{
logger.WriteTrace(string.Format("Iteration on getting items performed: {0}", position.PagingInfo), SeverityLevel.Verbose);
}
else
{
logger.WriteTrace("Getting all items finished.", SeverityLevel.Verbose);
}
logger.Flush();
}
}
catch (Exception ex)
{
logger.WriteException(ex);
}
}
while (position != null);
return result;
}
也许事件是一种选择,但也可能有一种更简单的方法来 "stream" 它们,而不是用列表一次返回所有事件。因此使用 yield
并更改为 IEnumerable<Item>
:
public static IEnumerable<Item> EnumerateItems(this List list, int rowLimit, List<string> fields, bool includeRoleAssignments, ILogger logger)
{
// ...
do
{
try
{
using (var clonedCtx = ctx.Clone(ctx.Url))
{
//...
camlQuery.ListItemCollectionPosition = position;
listItems = listWithClonedContext.GetItems(camlQuery);
// ...
foreach(Item x in listItems)
{
yield return x;
}
position = listItems.ListItemCollectionPosition;
// ...
}
while (position != null);
}
通过这种方式,您可以在获取它们时开始处理它们,或者您可以过滤它们,例如使用 Where
、Skip
或 Take
而无需将它们全部加载到内存中第一.
我有一个函数可以从 SharePoint 列表中获取 x 个项目。它分批获取项目。在每批之后我对物品做一些事情,销毁所有东西并拿下一批进行计算。我目前考虑使用事件。所以每批都有一个事件。这是正确的策略还是有更好的方法?我在考虑匿名函数或类似的东西?
public static List<Item> GetAllItems(this List list, int rowLimit, List<string> fields, bool includeRoleAssignments, ILogger logger)
{
var result = new List<Item>();
var ctx = list.Context;
ListItemCollectionPosition position = null;
var camlQuery = new CamlQuery();
camlQuery.ViewXml =
@"<View Scope='RecursiveAll'>
<Query>
<OrderBy Override='TRUE'><FieldRef Name='ID'/></OrderBy>
</Query>
<ViewFields></ViewFields>" +
"<RowLimit Paged='TRUE'>" + rowLimit + "</RowLimit>" +
"</View>";
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
do
{
try
{
using (var clonedCtx = ctx.Clone(ctx.Url))
{
List listWithClonedContext = clonedCtx.Web.Lists.GetByTitle(list.Title);
clonedCtx.Load(listWithClonedContext);
clonedCtx.ExecuteQuery();
ListItemCollection listItems = null;
camlQuery.ListItemCollectionPosition = position;
listItems = listWithClonedContext.GetItems(camlQuery);
foreach (string field in fields)
{
clonedCtx.Load(listItems, includes => includes.Include(i => i[field]));
}
if (!includeRoleAssignments) {
clonedCtx.Load(listItems, item => item.ListItemCollectionPosition);
}
else {
clonedCtx.Load(listItems, item =>
item.ListItemCollectionPosition,
item => item.Include(
i => i.RoleAssignments.Include(
ra => ra.Member,
ra => ra.Member.LoginName,
ra => ra.RoleDefinitionBindings.Include(rd => rd.Description, rd => rd.Name))));
}
clonedCtx.Load(listItems, item => item.ListItemCollectionPosition);
clonedCtx.ExecuteQueryWithIncrementalRetry(3, 1, logger);
// here i want to do something with items before next loop/batch
position = listItems.ListItemCollectionPosition;
if (position != null)
{
logger.WriteTrace(string.Format("Iteration on getting items performed: {0}", position.PagingInfo), SeverityLevel.Verbose);
}
else
{
logger.WriteTrace("Getting all items finished.", SeverityLevel.Verbose);
}
logger.Flush();
}
}
catch (Exception ex)
{
logger.WriteException(ex);
}
}
while (position != null);
return result;
}
也许事件是一种选择,但也可能有一种更简单的方法来 "stream" 它们,而不是用列表一次返回所有事件。因此使用 yield
并更改为 IEnumerable<Item>
:
public static IEnumerable<Item> EnumerateItems(this List list, int rowLimit, List<string> fields, bool includeRoleAssignments, ILogger logger)
{
// ...
do
{
try
{
using (var clonedCtx = ctx.Clone(ctx.Url))
{
//...
camlQuery.ListItemCollectionPosition = position;
listItems = listWithClonedContext.GetItems(camlQuery);
// ...
foreach(Item x in listItems)
{
yield return x;
}
position = listItems.ListItemCollectionPosition;
// ...
}
while (position != null);
}
通过这种方式,您可以在获取它们时开始处理它们,或者您可以过滤它们,例如使用 Where
、Skip
或 Take
而无需将它们全部加载到内存中第一.