Exchange Web 服务:使用 FindItemsResult- 进行批处理
我正在编写一个应用程序来使用 Exchange Web 服务处理电子邮件附件。
我的问题区域的总体结构如下:
public static void Main()
{
FindItemsResults<Item> findResults = FindItems();
foreach (Item item in findResults)
{
DoSomethingWithItem(item);
}
}
public static FindItemsResults<Item> FindItems()
{
FindItemsResults<Item> findResults;
ItemView view = new ItemView(10); //batching 10 at a time
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Ascending);
view.PropertySet = new PropertySet(
BasePropertySet.IdOnly,
ItemSchema.Subject,
ItemSchema.DateTimeReceived);
findResults = service.FindItems(
WellKnownFolderName.Inbox,
new SearchFilter.SearchFilterCollection(
LogicalOperator.Or,
new SearchFilter.ContainsSubstring(ItemSchema.Subject, Properties.Settings.Default.EmailSubject)),
view);
//return set of emails
return findResults;
}
起初,这看起来不错 - 它很好地处理了我之前的测试示例。但是当我开始使用批量加载进行测试时,我意识到它只处理前 10 个项目,因为我指定了 10 个项目的批量大小 (ItemView view = new ItemView(10
)),但是我没有检查更多批次。
我本来可以简单地增加批处理大小,但后来快速谷歌一下,我发现了一个更好的例子:
public static FindItemsResults<Item> FindItems()
{
FindItemsResults<Item> findResults;
ItemView view = new ItemView(10, 0, OffsetBasePoint.Beginning);
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Ascending);
view.PropertySet = new PropertySet(
BasePropertySet.IdOnly,
ItemSchema.Subject,
ItemSchema.DateTimeReceived);
do
{
findResults = service.FindItems(
WellKnownFolderName.Inbox,
new SearchFilter.SearchFilterCollection(
LogicalOperator.Or,
new SearchFilter.ContainsSubstring(ItemSchema.Subject, Properties.Settings.Default.EmailSubject)),
view);
//any more batches?
if (findResults.NextPageOffset.HasValue)
{
view.Offset = findResults.NextPageOffset.Value;
}
}
while (findResults.MoreAvailable);
return findResults;
}
这个循环遍历了我想扔给它的尽可能多的电子邮件,但由于我尚不明白的原因, foreach 循环现在只处理 findResults 中的第一项。
即使 findResults 包含多个项目 (findResults.Items.Count
> 1),在我的第二个示例中,findResults.MoreAvailable
= false。公平地说,我之前已经循环浏览过这些批次,因此我查看最后一批的末尾是有道理的。
但是我如何重置 findResults 以便它能够处理整个批次?我尝试设置 findResults.MoreAvailable 但它是只读的...我错过了什么?
结论:
好的,所以我可以一次处理一批项目,也可以将每批中的每个项目添加到列表中并稍后处理它们,就像我目前所做的那样。
他们之间没有太多的关系;我最初开始使用列表,但我会进一步考虑这个选择。
I'm writing an app to process email attachments, using Exchange Web Services.
The general structure of my problem area is as follows:
public static void Main()
{
FindItemsResults<Item> findResults = FindItems();
foreach (Item item in findResults)
{
DoSomethingWithItem(item);
}
}
public static FindItemsResults<Item> FindItems()
{
FindItemsResults<Item> findResults;
ItemView view = new ItemView(10); //batching 10 at a time
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Ascending);
view.PropertySet = new PropertySet(
BasePropertySet.IdOnly,
ItemSchema.Subject,
ItemSchema.DateTimeReceived);
findResults = service.FindItems(
WellKnownFolderName.Inbox,
new SearchFilter.SearchFilterCollection(
LogicalOperator.Or,
new SearchFilter.ContainsSubstring(ItemSchema.Subject, Properties.Settings.Default.EmailSubject)),
view);
//return set of emails
return findResults;
}
At first, this looked OK - it processed my earlier test examples perfectly well. But when I start testing with bulk loads, I realised that it was only processing the first 10 items, since I was specifying a batch size of 10 items (ItemView view = new ItemView(10
)), but I wasn't checking for further batches.
I could have simply increased the batch size, but a quick google later, I found a better example:
public static FindItemsResults<Item> FindItems()
{
FindItemsResults<Item> findResults;
ItemView view = new ItemView(10, 0, OffsetBasePoint.Beginning);
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Ascending);
view.PropertySet = new PropertySet(
BasePropertySet.IdOnly,
ItemSchema.Subject,
ItemSchema.DateTimeReceived);
do
{
findResults = service.FindItems(
WellKnownFolderName.Inbox,
new SearchFilter.SearchFilterCollection(
LogicalOperator.Or,
new SearchFilter.ContainsSubstring(ItemSchema.Subject, Properties.Settings.Default.EmailSubject)),
view);
//any more batches?
if (findResults.NextPageOffset.HasValue)
{
view.Offset = findResults.NextPageOffset.Value;
}
}
while (findResults.MoreAvailable);
return findResults;
}
This loops through as many emails as I care to throw at it, but for reasons I can't yet understand, the foreach loop now only processes the first item in findResults.
Even though findResults contains more than one item (findResults.Items.Count
> 1), with my second example, findResults.MoreAvailable
= false. Fair enough, I've looped through the batches earlier, so it makes sense that I'm looking at the end of the last batch.
But how do I reset findResults so that it will process the whole lot? I tried setting findResults.MoreAvailable but it is readonly... What am I missing?
CONCLUSION:
OK, so I can either process the items one batch at a time, or I can add each item in each batch to a List and process them later, as I currently do.
There is not a lot between them; I've initially started using a List, but I'll consider the choice further.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在我看来,您的主要问题是您尝试定义一个返回
FindItemsResults
的函数。如果您使用结果配对,您将没有这种类型的对象。而不是在检索每个新页面时,FindItemsResults
将被覆盖。以下示例显示收件箱中所有项目的主题:该代码在控制台输出上显示主题。如果您想以其他方式使用
EmailMessage
或MeetingRequest
,您应该修改对应的代码。您还可以定义一个委托,它对找到的EmailMessage
或MeetingRequest
执行某些操作,并在Console.WriteLine
的位置调用该委托。如果您确实需要在某个地方相同的所有项目,那么您将必须创建一些集合,例如List
,在其中填写函数并返回,而不是FindItemsResults
> 您目前正在做的事情。It seems to my that your main problem is that you try define a function which returns
FindItemsResults<Item>
. If you use paring of results you will have not one object of this type. Instead of that on retrieving of every new page theFindItemsResults<Item>
will be overwritten. Following example display subjects of all items from theInbox
:The code display the subjects on the console output. If you want to use
EmailMessage
orMeetingRequest
in another way you should modify the code correspondent. You can also define a delegate which do something with the foundEmailMessage
orMeetingRequest
and call the delegate on the place ofConsole.WriteLine
. If you do need to same all items somewhere, then you will have to create some collection likeList<Item>
, fill there in the function and return instead ofFindItemsResults<Item>
which you currently do.