Exchange Web服务:使用FindItemsResult <item> </item>进行批处理

时间:2010-09-30 17:09:41

标签: c# exchangewebservices ews-managed-api

我正在编写一个使用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&gt; 1),我的第二个示例findResults.MoreAvailable = false。很公平,我早先已经完成了批量操作,所以我看到最后一批的结尾是有道理的。

但是如何重置findResults以便它将处理整个批次?我尝试设置findResults.MoreAvailable但它只是readonly ...我错过了什么?

结论:

好的,所以我可以一次处理一个项目,或者我可以将每个批次中的每个项目添加到List中,然后像我现在一样处理它们。

他们之间没有太多关系;我最初开始使用List,但我会进一步考虑这个选择。

1 个答案:

答案 0 :(得分:8)

在我看来,你的主要问题是你尝试定义一个返回FindItemsResults<Item>的函数。如果使用配对结果,您将拥有此类型的不是一个对象。而不是在检索每个新页面时,FindItemsResults<Item>将被覆盖。以下示例显示Inbox

中所有项目的主题
ItemView view = new ItemView(10, 0, OffsetBasePoint.Beginning);
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending);
view.PropertySet = new PropertySet(
    BasePropertySet.IdOnly,
    ItemSchema.Subject,
    ItemSchema.DateTimeReceived);

// save the folder where we will make searching to do this one time
Folder myInbox = Folder.Bind(service, WellKnownFolderName.Inbox);

FindItemsResults<Item> findResults;

do
{
    findResults = myInbox.FindItems(
        new SearchFilter.ContainsSubstring(ItemSchema.Subject,
                Properties.Settings.Default.EmailSubject)),
        view);

    foreach (Item item in findResults)
    {
        // Do something with the item.
        Console.WriteLine();
        if (item is EmailMessage)
        {
            EmailMessage em = item as EmailMessage;
            Console.WriteLine("Subject: \"{0}\"", em.Subject);
        }
        else if (item is MeetingRequest)
        {
            MeetingRequest mr = item as MeetingRequest;
            Console.WriteLine("Subject: \"{0}\"", mr.Subject);
        }
        else
        {
            // we can handle other item types
        }
    }

    //any more batches?
    if (findResults.NextPageOffset.HasValue)
    {
        view.Offset = findResults.NextPageOffset.Value;
    }
}
while (findResults.MoreAvailable);

代码显示控制台输出上的主题。如果您想以其他方式使用EmailMessageMeetingRequest,则应修改代码对应方。您还可以定义一个委托,该委托对找到的EmailMessageMeetingRequest执行某些操作,并在Console.WriteLine的位置调用该委托。如果你确实需要在某个地方使用相同的所有项目,那么你必须创建一些像List<Item>这样的集合,填写函数并返回而不是你当前所做的FindItemsResults<Item>