2012-08-17 4 views
11

Si je fais ceci:Comment faire pagination avec des services Web Exchange calendarview

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

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

Je reçois parfois une exception que trop d'articles ont été trouvés.

"Vous avez dépassé le nombre maximal d'objets pouvant être renvoyés pour l'opération de recherche Utilisez la pagination pour réduire la taille du résultat et réessayer votre demande."

CalendarView prend en charge un constructeur qui me permettra de spécifier MaxItemsReturned, mais je ne peux pas comprendre comment je l'appellerais à nouveau, en spécifiant le offset pour la pagination. ItemView a ce constructeur:

public ItemView(int pageSize, int offset) 

Et l'utilisation de c'est évident.

Qu'en est-il de CalendarView? Comment fait-on la pagination avec un CalendarView?

Je pourrais réduire la plage de dates à une durée plus courte, mais il n'y a toujours aucun moyen de déterminer si cela fonctionnera à coup sûr.

Répondre

8

CalendarView n'est pas réellement dérivé de PagedView, donc toute la logique de pagination que vous attendez n'est pas possible. MaxItemsReturned est plus d'une limite supérieure à une taille de page. L'erreur renvoyée est plus pertinente pour les types de vue dérivés PagedView. J'ai joué avec un peu PowerShell pour émuler la pagination en roulant la fenêtre CalendarView en fonction du dernier élément renvoyé, mais malheureusement, la logique derrière l'expansion CalendarView et Appointment rend impossible d'obtenir exactement ce dont vous avez besoin. Fondamentalement, comme c'est le cas de l'expansion, il va s'arrêter à "N" éléments, mais vous pouvez avoir plus d'un rendez-vous qui commence à la même heure et il peut vous donner un, mais pas le reste. En outre, tous les rendez-vous qui chevauchent la fenêtre seront inclus, de sorte que le code ci-dessous entrerait dans une boucle infinie si vous aviez 50 rendez-vous sur le calendrier qui avaient tous le même heure de début.

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

Malheureusement, l'expansion et la logique de chevauchement signifie que vous obtiendrez des doublons ainsi, au moins un double pour chaque appel au-delà de la première. Si je devais écrire du code en utilisant CalendarView, j'utiliserais probablement un MaxItemsReturned de 1000 (c'est aussi la limite qui vous jette dans la condition d'erreur si vous ne spécifiez pas MaxItemsReturned). Si vous obtenez tous en un seul appel, vous êtes bon. Si vous devez effectuer un second appel, vous devrez effectuer un travail supplémentaire pour déduire le jeu de résultats. Je vais également essayer de limiter le fardeau sur le serveur en utilisant une fenêtre de date aussi étroite que possible dans CalendarView puisque vous demandez à Exchange de calculer l'expansion des rendez-vous récurrents sur l'ensemble de la période. Cela peut être une opération assez coûteuse pour le serveur.

+0

Bonnes choses RickH, mais toujours pas assez déterministe pour moi. Ce que j'ai fait entre-temps est de diviser l'intervalle en mois et d'utiliser 'CalendarView' pour chaque mois. Ça semble fonctionner correctement. – tig

+0

Le «coût de traitement du serveur» est fondamentalement le même, peu importe si je le fais pour une année complète ou avec des plages de 12 mois, non? – tig

+0

Même si votre réponse ne résout pas vraiment mon problème, vous fournissez une réponse: Il n'est pas possible d'effectuer une pagination de style PagedmView avec un calendrier. Donc, marquer cela comme la réponse. – tig

0

Vous pouvez utiliser ItemView et SearchFilter aux rendez-vous interroger:

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

Ceci n'élargit pas les occurrences de masters récurrents et fournit donc une vue incomplète du calender autant que je peux dire. C'est pourquoi le 'CalendarView' est si utile (sauf pour le fait qu'il ne fonctionne pas bien) – jessehouwing

0

Vous pouvez encore paginer la fonction FindAppointments manipulation du calendarview les dates de début.

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

Bien que je ne sais pas si elles viennent dans l'ordre. Si ce n'est pas le cas, vous devrez peut-être utiliser la dernière date de début envent et supprimer les doublons.

Questions connexes