Веб-службы Exchange: пакетная обработка с помощью FindItemsResult ‹Item›

Я пишу приложение для обработки вложений электронной почты с помощью веб-служб Exchange.

Общая структура моей проблемной зоны следующая:

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)), но я не проверял наличие следующих партий.

Я мог бы просто увеличить размер пакета, но, посмотрев позже в Google, я нашел лучший пример:

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, но он доступен только для чтения ... Что мне не хватает?

ЗАКЛЮЧЕНИЕ:

Хорошо, поэтому я могу либо обрабатывать элементы по одной партии за раз, либо я могу добавить каждый элемент в каждой партии в список и обрабатывать их позже, как я это делаю сейчас.

Между ними нет ничего особенного; Сначала я начал использовать список, но позже рассмотрю выбор.


person CJM    schedule 30.09.2010    source источник


Ответы (1)


Мне кажется, что ваша основная проблема в том, что вы пытаетесь определить функцию, которая возвращает 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);

Код отображает темы на выходе консоли. Если вы хотите использовать EmailMessage или MeetingRequest по-другому, вам следует изменить соответствующий код. Вы также можете определить делегата, который что-то сделает с найденными EmailMessage или MeetingRequest и вызовет делегата вместо Console.WriteLine. Если вам действительно нужно где-то объединить все элементы, вам нужно будет создать некоторую коллекцию, например List<Item>, заполнить ее функцией и вернуть вместо FindItemsResults<Item>, что вы сейчас делаете.

person Oleg    schedule 02.10.2010