2012-08-17 40 views
11

Si hago esto:Cómo hacer paginación con Exchange Web Services CalendarView

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

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

a veces tengo una excepción que se encontraron demasiados elementos.

"Ha excedido la cantidad máxima de objetos que pueden devolverse para la operación de búsqueda. Utilice la búsqueda para reducir el tamaño del resultado y vuelva a intentar su solicitud".

CalendarView es compatible con un constructor que me permita especificar MaxItemsReturned, pero no entiendo cómo lo llamaría de nuevo, especificando el offset para buscar. ItemView tiene este constructor:

public ItemView(int pageSize, int offset) 

Y el uso de eso es obvio.

¿Qué hay de CalendarView? ¿Cómo se hace una búsqueda con un CalendarView?

Podría reducir el intervalo de fechas para que sea más corto, pero aún no hay forma de determinar si funcionará con seguridad.

Respuesta

8

CalendarView en realidad no se deriva de PagedView, por lo que no es posible toda la lógica de búsqueda que esperas. MaxItemsReturned es más un límite superior que un tamaño de página. El error que se devuelve es más relevante para los tipos de vista derivados de PagedView.

Jugué con PowerShell para emular la paginación moviendo la ventana de CalendarView según el último elemento devuelto, pero desafortunadamente la lógica detrás de la expansión CalendarView y Appointment hace que sea imposible obtener exactamente lo que necesita. Básicamente, como lo hace con la expansión, se detendrá en los elementos "N", pero es posible que tenga más de una cita que comience exactamente al mismo tiempo y le puede dar una, pero no el resto. Además, cualquier cita que se superponga a la ventana se incluirá, por lo que el código siguiente entraría en un bucle infinito si tuviera 50 citas en el calendario que todas tuvieran la misma hora de inicio.

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)" 

Por desgracia, la expansión y la lógica de superposición significa que obtendrá duplicados de esta manera, al menos un duplicado para cada llamada más allá de la primera.

Si tuviera que escribir código usando CalendarView, probablemente usaría un MaxItemsReturned de 1000 (este es también el límite que lo arroja a la condición de error si no especifica MaxItemsReturned). Si los recibe a todos en una sola llamada, está bien. Si tiene que hacer una segunda llamada, tendrá que hacer un trabajo adicional para deduplicar el conjunto de resultados. También trataría de limitar la carga en el servidor utilizando una ventana de fecha tan estrecha como sea posible en CalendarView, ya que le pide a Exchange que calcule la expansión de las citas recurrentes en todo el lapso de tiempo. Puede ser una operación bastante costosa para el servidor.

+0

Lo bueno RickH, pero todavía no es lo suficientemente determinista para mí. Lo que he hecho mientras tanto es dividir el lapso en meses y usar 'CalendarView' para cada mes. Parece estar funcionando bien. – tig

+0

El 'costo de procesamiento del servidor' es básicamente el mismo independientemente de si lo hago durante un año completo o con intervalos de 12 meses, ¿no? – tig

+0

Aunque su respuesta no soluciona realmente mi problema, proporciona una respuesta: No es posible hacer paginación de estilo de PagedmView con un calendario. Marcando esto como la respuesta. – tig

0

Puede utilizar ItemView y SearchFilter para consultar las citas:

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; 
} 
+3

Esto no expande las ocurrencias de maestros recurrentes y, por lo tanto, proporciona una vista incompleta del calendario por lo que puedo ver. Es por eso que 'CalendarView' es tan útil (excepto por el hecho de que no pagina bien) – jessehouwing

0

fijas que se pueden paginar la función FindAppointments la manipulación de la CalendarView fechas de inicio.

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); 
} 

Aunque no sé si vienen en orden. Si no lo hacen, es posible que tenga que usar la última fecha de inicio del invento y eliminar los duplicados.