FetchAppointments Event - Handling Large Datasets
- 5 minutes to read
This topic describes a technique for minimizing data queried by the SchedulerDataStorage from its external data source. This approach may significantly improve the performance of a scheduling application.
To do this, you can handle the SchedulerDataStorage.FetchAppointments event, which is capable of filtering and prefetching data.
FetchAppointments Event in Detail
The FetchAppointments event is designed to reduce the amount of data fetched from the data source at one time. When the Scheduler changes its visible time interval, it requests Storage for the displayed appointments. If the FetchAppointments event is handled, the event handler fetches appointments; otherwise, the SchedulerDataStorage component operates according to its built-in logic - the SchedulerDataStorage has a cache that contains previously fetched appointments. Note that cache operations may retrieve an excessive amount of appointment data. By handling the FetchAppointment event, you can implement your own logic for populating the data source, thus reducing the amount of appointments data retrieves.
A parameterized query should be used to fill the data adapters with data. In this instance, the query fetches appointment data for the required time intervals only. You can decide to extend the time interval to ensure prefetching, and fill the SchedulerDataStorage's appointment cache with extra data. The implementation depends on the view the user is switching to, and the assumptions as to how the user will navigate dates.
Note that all requested time intervals should be populated with data, and it does not make sense to differentiate, or even prevent, specific data from being fetched. The task is to optimize data access, and not to prevent data for specific intervals from being fetched at all. You can implement an appropriate caching strategy, as there is no general solution for all cases.
If the SchedulerDataStorage.FetchAppointments event is handled, the Scheduler does not rely on its own, built-in caching strategy. The FetchAppointments event occurs in situations that do not involve changes in the displayed data, such as control resizing. To improve performance, treat these cases as your needs dictate, and decide whether to query the data source for appointment data again or leave the Storage data intact.
To minimize the amount of data loaded, and decrease the number of queries from the FetchAppointments event handler, do not highlight days with appointments in the DateNavigator control (set the DateNavigator.BoldAppointmentDates property to false).
Recently, the FetchAppointments event occurs too often when appointment are being inserted/deleted/modified, on visible interval changing and in other situations. It caused several problems.
Starting with version 15.2, the FetchAppointments event occurs when the visible interval or resource collection is changed, or when the SchedulerControl.RefreshData method is called. However the event is not raised for appointment changes.
The SchedulerDataStorage.EnableSmartFetch property regulates this behavior. The property is true by default to ensure that the FetchAppointments event occurs in the situations described above. To restore the former behavior of the FetchAppointments event set the EnableSmartFetch property to false.
Special Notes on Recurring Appointments
Recurring appointment is a special case. A recurring appointment series is never stored in the underlying data source. The data source only contains records for the pattern, and changed and deleted appointments. For example, you have 3 pattern appointments, where each appointment generates a series of 10 regular appointments. Thus, only 3 pattern appointments are stored in the underlying data source, in place of 30 appointments. When a pattern appointment is loaded into the SchedulerControl, the control calculates the recurring series and displays appointments from the series in the active view.
Once you change or delete any appointment from that series, a new appointment is created with a corresponding Appointment.Type - AppointmentType.ChangedOccurrence (value = 3) or AppointmentType.DeletedOccurrence (value = 4 ), and this appointment is stored in the data source as a separate record.
The SchedulerControl generates recurring series with occurrences based on the pattern's recurring rule and removes deleted and changed occurrences from the chain. However, if the changed occurrence is moved outside of the queryable time range, it is not loaded and the SchedulerControl will generate an occurrence with the corresponding recurrence index instead of this (non-loaded) changed occurrence. To fix this problem, use the Appointment.OriginalOccurrenceStart and Appointment.OriginalOccurrenceEnd properties in a query instead of the regular Appointment.Start and Appointment.End properties.
The OriginalOccurrenceStart and OriginalOccurrenceEnd properties should be mapped to the corresponding fields in the data source. You can create a new data source which contains these fields or update an existing data source.
To update an existing data source, perform the following steps:
- Modify the data source to include two DateTime fields.
- Add mappings. Map two fields added in the previous step to the Appointment.OriginalOccurrenceStart and Appointment.OriginalOccurrenceEnd properties.
- Call the OriginalOccurrenceDateHelper.Update method to update the data source fields. This method should be called only once, and only after all existing appointments are fully loaded. After updating the fields it is no longer required and you can delete it from your code.
- Modify the queries run in the SchedulerDataStorage.FetchAppointments event handler. Replace the Start and End values with the OriginalOccurrenceStart and OriginalOccurrenceEnd values.