3

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) が含まれていますが、2 番目の例ではfindResults.MoreAvailable= false です。当然のことながら、以前にバッチをループ処理したので、最後のバッチの最後を見ているのは理にかなっています。

しかし、findResults をリセットしてすべてを処理するにはどうすればよいでしょうか。findResults.MoreAvailable を設定しようとしましたが、読み取り専用です...何が欠けていますか?

結論:

では、アイテムを一度に 1 バッチずつ処理するか、現在行っているように、各バッチの各アイテムを List に追加して後で処理することができます。

それらの間には多くはありません。最初はリストを使い始めましたが、選択をさらに検討します。

4

1 に答える 1

8

あなたの主な問題は、 を返す関数を定義しようとすることだと私には思えますFindItemsResults<Item>。結果のペアリングを使用すると、このタイプのオブジェクトは1 つもありません。その代わりに、すべての新しいページを取得するとき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また、見つかったorで何かを行うデリゲートを定義MeetingRequestし、代わりにデリゲートを呼び出すこともできますConsole.WriteLine。どこかですべてのアイテムを同じにする必要がある場合は、 のようなコレクションを作成List<Item>し、そこに関数を入力しFindItemsResults<Item>て、現在行っている代わりに返す必要があります。

于 2010-10-02T21:39:42.167 に答える