corelibraries-devexpress-dot-xtrascheduler-dot-schedulerstoragebase-e02a8e3c.md
Occurs before the SchedulerStorageBase starts retrieving the appointments for the specified time interval.
Namespace : DevExpress.XtraScheduler
Assembly : DevExpress.XtraScheduler.v25.2.Core.Desktop.dll
NuGet Package : DevExpress.Scheduler.CoreDesktop
public event FetchAppointmentsEventHandler FetchAppointments
Public Event FetchAppointments As FetchAppointmentsEventHandler
The FetchAppointments event's data class is FetchAppointmentsEventArgs. The following properties provide information specific to this event:
| Property | Description |
|---|---|
| ForceReloadAppointments | Gets or sets whether the appointments collection should be reloaded after handling the SchedulerStorageBase.FetchAppointments event. |
| Interval | Gets the time interval which the event was raised for. Inherited from TimeIntervalEventArgs. |
Handle the FetchAppointments event to limit the number of appointments fetched from the data source. This can be useful when working with a large amount of data, and only a small part of it needs to be loaded at one time.
The FetchAppointments event reduces the amount of data fetched from slow data sources with large data sets. Consider the interaction between the Scheduler, the Storage and the Data Source. When the Scheduler changes its displayed time interval, it requests the Storage for appointments to display. The Storage generates the FetchAppointments event and queries the Data Source for more data. This query may result in sending an excessive amount of appointment data. To prevent this, and to get only data that is required for the visible time interval, you can handle the FetchAppointment event. In the event handler, you should modify the query to get only the required data.
If the FetchAppointments event is handled, the Scheduler does not rely on its own, built-in caching strategy. The FetchAppointments event occurs in situations which do not involve any changes in displayed data, such as control resizing. To improve performance, treat these cases as your needs dictate and decide for yourself whether appointment data should be queried again or remain intact.
Certain scenarios may benefit from testing the ISchedulerStateService.IsDataRefreshAllowed property before fetching data in the FetchAppointments event handler and perform the operation only if its value is true. In general, it is not required.
The following requirements should be met when handling the FetchAppointments event:
To pad the time interval used to query appointments, we use a range of seven days (PADDING_DAYS constant). You can specify another interval arbitrarily.
Note
A complete sample project is available at https://github.com/DevExpress-Examples/winforms-scheduler-optimize-performance-large-dataset
void schedulerStorage1_FetchAppointments(object sender, FetchAppointmentsEventArgs e) {
ResourceBaseCollection resourcesVisible = schedulerControl1.ActiveView.GetResources();
var differentResources = resourcesVisible.Except(lastQueriedResources);
// If a different resource is displayed or the visible time interval intersects the time interval used in a recent query, fetch the data.
if ((differentResources.Count() != 0) || (e.Interval.Start < lastQueriedTimeInterval.Start) || (e.Interval.End > lastQueriedTimeInterval.End)) {
QueryAppointmentDataSource(e, resourcesVisible);
lastQueriedResources = resourcesVisible;
lastQueriedTimeInterval = e.Interval;
}
}
private void QueryAppointmentDataSource(FetchAppointmentsEventArgs e, ResourceBaseCollection resources) {
string resListString = String.Join(",", resources.Select(res => res.Id.ToString()));
// Modify the FillBy query to fetch appointments only for the specified resources.
appointmentsTableAdapter.Commands[1].CommandText =
String.Format("SELECT Appointments.* FROM Appointments WHERE (((OriginalOccurrenceStart <= @End) AND(OriginalOccurrenceEnd >= @Start)) OR ((Appointments.StartDate <= @End) AND(EndDate >= @Start))) AND (ResourceID IN ({0})) OR (Type != 0)", resListString);
appointmentsTableAdapter.FillBy(this.scheduleTestDataSet.Appointments, e.Interval.Start.AddDays(-PADDING_DAYS), e.Interval.End.AddDays(PADDING_DAYS));
queryExecutionCounter++;
}
Private Sub schedulerStorage1_FetchAppointments(ByVal sender As Object, ByVal e As FetchAppointmentsEventArgs)
Dim resourcesVisible As ResourceBaseCollection = schedulerControl1.ActiveView.GetResources()
Dim differentResources = resourcesVisible.Except(lastQueriedResources)
' If a different resource is displayed or the visible time interval intersects the time interval used in a recent query, fetch the data.
If (differentResources.Count() <> 0) OrElse (e.Interval.Start < lastQueriedTimeInterval.Start) OrElse (e.Interval.End > lastQueriedTimeInterval.End) Then
QueryAppointmentDataSource(e, resourcesVisible)
lastQueriedResources = resourcesVisible
lastQueriedTimeInterval = e.Interval
End If
End Sub
Private Sub QueryAppointmentDataSource(ByVal e As FetchAppointmentsEventArgs, ByVal resources As ResourceBaseCollection)
Dim resListString As String = String.Join(",", resources.Select(Function(res) res.Id.ToString()))
' Modify the FillBy query to fetch appointments only for the specified resources.
appointmentsTableAdapter.Commands(1).CommandText = String.Format("SELECT Appointments.* FROM Appointments WHERE (((OriginalOccurrenceStart <= @End) AND(OriginalOccurrenceEnd >= @Start)) OR ((Appointments.StartDate <= @End) AND(EndDate >= @Start))) AND (ResourceID IN ({0})) OR (Type != 0)", resListString)
appointmentsTableAdapter.FillBy(Me.scheduleTestDataSet.Appointments, e.Interval.Start.AddDays(-PADDING_DAYS), e.Interval.End.AddDays(PADDING_DAYS))
queryExecutionCounter += 1
End Sub
Note
Prior to v.15.2 , the FetchAppointments event occurs in situations, which do not involve any changes in displayed data ranges. This behavior may result in unhandled exceptions if the event was not properly handled. To solve the problem, we have implemented additional internal criteria that should be met before the event is raised. Starting with v.15.2, the FetchAppointments event fires not so often as it did before and does not fire at all in certain situations. This behavior may affect the customer’s application logic. If you experience unwanted side effects due to the newly introduced behavior, set the SchedulerStorageBase.EnableSmartFetch option to false to revert to the former mechanism of raising the FetchAppointments event.
Note
The Date Navigator control, if present on the form and linked with the Scheduler control, could also cause multiple FetchAppointments events to occur. When the DateNavigator.BoldAppointmentDates is set to true , DateNavigator requests the appointment information for highlighting the corresponding dates.
See the FetchAppointments Event - Handling Large Datasets document for more information.
The following code snippet (auto-collected from DevExpress Examples) contains a reference to the FetchAppointments event.
Note
The algorithm used to collect these code examples remains a work in progress. Accordingly, the links and snippets below may produce inaccurate results. If you encounter an issue with code examples below, please use the feedback form on this page to report the issue.
winforms-scheduler-handle-fetchappointments-event-entity-framework/CS/Form1.cs#L17
schedulerControl1.ActiveViewType = SchedulerViewType.FullWeek;
schedulerControl1.Storage.FetchAppointments += Storage_FetchAppointments;
winforms-scheduler-handle-fetchappointments-event-entity-framework/VB/Form1.vb#L17
schedulerControl1.ActiveViewType = SchedulerViewType.FullWeek
AddHandler schedulerControl1.Storage.FetchAppointments, AddressOf Storage_FetchAppointments
SetupMappings()
See Also
How to: Use the FetchAppointments Event for Faster Appointment Loading
FetchAppointments Event - Handling Large Datasets