14

如果我这样做:

_calendar = (CalendarFolder)Folder.Bind(_service, WellKnownFolderName.Calendar);

var findResults = _calendar.FindAppointments(
    new CalendarView(startDate.Date, endDate.Date)
);

我有时会收到一个异常,即找到了太多项目。

“您已超出查找操作可以返回的最大对象数。使用分页减小结果大小,然后重试您的请求。”

CalendarView支持一个让我指定的构造函数MaxItemsReturned,但我不知道如何再次调用它,指定offsetfor 分页。ItemView有这个构造函数:

 public ItemView(int pageSize, int offset)

它的用法很明显。

怎么样CalendarView?如何使用 a 进行分页CalendarView

我可以将日期范围缩短为更短的跨度,但仍然无法确定它是否会起作用。

4

3 回答 3

8

CalendarView实际上并不是从PagedView派生的,因此您期望的所有分页逻辑都是不可能的。MaxItemsReturned 更多的是一个上限而不是页面大小。返回的错误与 PagedView 派生的视图类型更相关。

我玩弄了一些 PowerShell,通过根据返回的最后一个项目滚动 CalendarView 窗口来模拟分页,但不幸的是,CalendarView 和 Appointment 扩展背后的逻辑使得无法准确获得所需的内容。基本上,就像它进行扩展一样,它会在“N”个项目上停止,但您可能有不止一个在同一时间开始的约会,它可能会给您一个,而不是其余的。此外,任何与窗口重叠的约会都将被包括在内,因此如果日历上有 50 个约会的开始时间相同,则下面的代码将进入无限循环。

Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"

$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
$cred = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials ($user , $passwd)
$service.UseDefaultCredentials = $false
$service.Credentials = $cred
$service.AutodiscoverUrl($user)

$num=50
$total=0
$propsetfc = [Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties
$calfolder = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar

$service.UserAgent = "EWSCalViewTest"
$calview = New-Object Microsoft.Exchange.WebServices.Data.CalendarView("1/1/2012","12/31/2012", $num)
$calview.PropertySet = $propsetfc

do {
    $findresults = $service.FindAppointments($calfolder,$calview)
    write-host  "Found:" $findresults.Items.Count "of" $findresults.TotalCount
    $calview.StartDate = $findresults.Items[$findresults.Items.Count-1].Start
    $total+=$findresults.Items.Count
} while($findresults.MoreAvailable)
write-host $total "total found (including dups)"

不幸的是,扩展和重叠逻辑意味着您将以这种方式得到重复,除了第一个调用之外,每个调用至少有一个重复。

如果我必须使用 CalendarView 编写代码,我可能会使用 1000 的 MaxItemsReturned(如果您不指定 MaxItemsReturned,这也是使您陷入错误状态的限制)。如果您在一个电话中获得所有信息,那您就很好。如果您必须进行第二次调用,那么您将不得不做一些额外的工作来对结果集进行重复数据删除。我还尝试通过在 CalendarView 中使用尽可能窄的日期窗口来限制服务器的负担,因为您要求 Exchange 计算整个时间跨度内定期约会的扩展。对于服务器来说,这可能是一项相当昂贵的操作。

于 2012-08-19T19:21:59.460 回答
1

您可以使用ItemViewSearchFilter查询约会:

var itemView = new ItemView(100, 0);
itemView.PropertySet = new PropertySet(BasePropertySet.IdOnly,
    ItemSchema.Subject, AppointmentSchema.Start, AppointmentSchema.End);

var filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And,
    new SearchFilter.IsEqualTo(ItemSchema.ItemClass, "IPM.Appointment"),
    new SearchFilter.IsGreaterThanOrEqualTo(AppointmentSchema.Start, startDate),
    new SearchFilter.IsLessThan(AppointmentSchema.Start, endDate));

bool moreAvailable = true;
while (moreAvailable)
{
    var result = _service.FindItems(WellKnownFolderName.Calendar, filter, itemView);

    foreach (var appointment in result.OfType<Appointment>())
    {
        DateTime start = appointment.Start;
        DateTime end = appointment.End;
        string subject = appointment.Subject;

        // ...
    }

    itemView.Offset += itemView.PageSize;
    moreAvailable = result.MoreAvailable;
}
于 2014-01-28T19:21:47.907 回答
1

您仍然可以对操纵 CalendarView 开始日期的 FindAppointments 函数进行分页。

var cal = CalendarFolder.Bind(_service, WellKnownFolderName.Calendar);
var cv = new CalendarView(start, end, 1000);

var appointments = new List<Appointment>();

var result = cal.FindAppointments(cv);

appointments.AddRange(result);

while (result.MoreAvailable)
{
     cv.StartDate = appointments.Last().Start;

     result = cal.FindAppointments(cv);

     appointments.AddRange(result);
}

虽然我不知道他们是否按顺序排列。如果他们不这样做,您可能必须使用最后一个活动开始日期并删除重复项。

于 2017-10-02T19:49:18.533 回答