Quelle est la meilleure façon de représenter les "événements récurrents" dans la base de données?
J'essaie de développer une application d'événement dépendante du planificateur et du calendrier en C#, pour laquelle une exigence cruciale est de représenter des événements récurrents dans la base de données. Quelle est la meilleure façon de représenter les événements récurrents dans une base de données?
Plus De Détails:
Lors de la création de l'événement, j'envoie également des invitations à certains utilisateurs et les invités devraient être autorisés à se connecter à la réunion uniquement pendant la fenêtre spécifiée (durée de la réunion) ou peuvent refuser la connexion lorsque le invitee tente de se connecter par exemple, 5 minutes avant le début prévu de la réunion.
6 réponses
Le sysjobs, sysjobsschedule et sysschedules tables dans SQL Server fait un assez bon travail de ce. Je ne réinventerais pas la roue, Je copierais simplement leur design.
Voici quelques-uns des champs importants de sysschedules
Freq_type
Fréquence à laquelle un travail s'exécute pour cette planification.
1 = Une seule fois
4 = quotidien
8 = Hebdomadaire
16 = mensuel
32 = mensuel, relatif à freq_interval
64 = S'exécute lorsque le service SQL Server Agent démarre
128 = s'Exécute lorsque l'ordinateur est inactif
Freq_interval
Jours pendant lesquels le travail est exécuté. Dépend de la valeur de freq_type. La valeur par défaut est 0, ce qui indique que freq_interval n'est pas utilisé. Valeur de l'effet freq_type sur freq_interval
1 (Une fois) freq_interval est inutilisé (0)
4 (tous les jours) tous les jours freq_interval
8 (hebdomadaire) freq_interval est un ou plusieurs des éléments suivants: 1 = dimanche 2 = Lundi 4 = mardi 8 = mercredi 16 = jeudi 32 = vendredi 64 = samedi
16 (mensuel) le jour freq_interval du mois
32 (mensuel, relatif) freq_interval est l'un des éléments suivants: 1 = dimanche 2 = lundi 3 = mardi 4 = mercredi 5 = jeudi 6 = vendredi 7 = samedi 8 = Jour 9 = Jour de la Semaine 10 = jour du week-end
64 (démarre lorsque SQL Server Agent service démarre) freq_interval est inutilisé (0)
128 (s'exécute lorsque l'ordinateur est inactif) freq_interval est inutilisé (0)
Freq_subday_type
Unités pour le freq_subday_interval. Peut être une des valeurs suivantes: Description de la valeur (Unité)
1 À l'heure spécifiée
2 Secondes
4 Minutes
8 Heures
Freq_subday_interval
Nombre de périodes freq_subday_type devant se produire entre l'exécution du travail.
Freq_relative_interval
Lorsque freq_interval se produit dans chaque mois, si freq_interval est 32 (mensuel relatif). Peut être l'une des valeurs suivantes:
0 = freq_relative_interval est inutilisé
1 = Premier
2 = Deuxième
4 = troisième
8 = Quatrième
16 = dernier
Freq_recurrence_factor
Nombre de semaines ou de mois entre la date prévue de l'exécution d'un travail. freq_recurrence_factor n'est utilisé que si freq_type vaut 8, 16 ou 32. Si cette colonne contient 0, freq_recurrence_factor est inutilisé.
Eh bien, pour stocker la règle de récurrence elle-même, vous pouvez utiliser une version réduite de RFC 5545 (et je vous suggère vraiment de la réduire fortement). Mis à part toute autre chose, qui le rendra facile à exporter dans d'autres applications Si vous le souhaitez.
Après avoir pris cette décision, pour le côté base de données, vous devez déterminer si vous voulez stocker chaque occurrence de l'événement, ou juste un enregistrement pour l'événement répété, en l'élargissant au fur et à mesure. Évidemment, il est beaucoup plus facile d'interroger la base de données lorsque vous avez déjà tout développé - mais cela le rend plus délicat à maintenir.
À moins que vous n'ayez envie d'écrire un SQL assez complexe qui peut être difficile à tester (et vous voudrez un lot de tests unitaires pour toutes sortes de cas de coin) je vous suggère de rendre la base de données elle-même relativement "stupide" et d'écrire la plupart de la logique métier dans un langage comme Java procédures en fonction de votre base de données, bien sûr.
Une autre chose que vous devez vous demander est de savoir si vous devez faire face à exceptions aux événements - un événement dans une série changeant l'heure/l'emplacement, etc.
J'ai une certaine expérience avec le calendrier (j'ai passé la majeure partie de l'année dernière à travailler sur le calendrier de Google Sync via ActiveSync) et je devrais vous avertir que les choses se compliquent vraiment rapidement. Tout ce que vous pouvez juger "hors de portée" est une bénédiction. En particulier, avez-vous besoin de travailler dans plusieurs fuseaux horaires?
Oh, et enfin-soyez très, très prudent lorsque vous faites de l'arithmétique réelle avec des opérations de calendrier. Si vous allez utiliser Java, , veuillez utiliser Joda Time plutôt que dans le haut-Calendar
/Date
des classes. Ils vous aideront beaucoup.
La réponse acceptée ici est trop alambiquée. Par exemple, si un événement se produit tous les 5 jours, le 5 est stocké dans freq_interval, mais s'il se produit toutes les 5 semaines, le 5 est stocké dans freq_recurrence. Le plus gros problème est que freq_interval signifie trois choses différentes en fonction de la valeur de freq_type (nombre de jours entre les occurrences pour la récurrence quotidienne, jour du mois pour la récurrence mensuelle, ou jours de la semaine pour hebdomadaire ou mensuel-relatif). En outre, le 1,2,4,8... la séquence de type est utilisé quand il est inutile et moins utile. Par exemple, freq_relative_interval ne peut être que "l'une des" valeurs possibles. Cela s'aligne avec une entrée de type boîte déroulante ou bouton radio, pas une entrée de type case à cocher où plusieurs choix peuvent être sélectionnés. Pour le codage, et pour la lisibilité humaine, cette séquence se met en travers et utilise simplement 1,2,3,4... est plus simple, plus efficace, plus approprié. Enfin, la plupart des applications de calendrier n'ont pas besoin d'intervalles de sous-jour (événements se produisant plusieurs fois par jour-toutes les secondes, minutes ou heures).
Mais, cela dit, cette réponse m'a aidé à affiner mes réflexions sur la façon dont je fais cela. Après le mélange et l'appariement avec d'autres articles et en allant de ce que je vois dans L'interface de calendrier Outlook et quelques autres sources, je viens avec ceci:
Revient
0 = aucune récurrence
1 = quotidien
2=hebdomadaire
3=mensuel
Recurs_interval
c'est combien de périodes entre récidive. Si l'événement se répète tous les 5 jours, cela aura un 5 et revient avez 1. Si l'événement se répète toutes les 2 semaines, ce sera un 2 et revient aura un 2.
Recurs_day
Si l'Utilisateur a sélectionné la récurrence de type mensuel, un jour donné du mois (ex: 10ème ou 14ème). C'est à cette date. La valeur est 0 si l'utilisateur n'a pas sélectionné la récurrence mensuelle ou spécifique du jour du mois. La valeur est de 1 à 31 autrement.
Recurs_ordinal
si l'Utilisateur a sélectionné une récurrence de type mensuel, mais un type ordinal de jour (ex: premier lundi, deuxième jeudi, dernier vendredi). Cela aura ce nombre ordinal. La valeur est 0 si l'utilisateur n'a pas sélectionné ce type de récurrence.
1=premier
2=deuxième
3=troisième
4=quatrième
5 = Dernier
Recurs_weekdays
pour la récurrence hebdomadaire et mensuelle-ordinale, cela stocke les jours de la semaine où la récurrence arriver.
1 = Dimanche
2 = lundi
4 = mardi
8 = mercredi
16 = jeudi
32 = vendredi
64 = samedi
Donc, les exemples:
Donc, toutes les 4 semaines le samedi et le dimanche serait
- récurs = 2 = = > récurrence hebdomadaire
- recurs_interval = 4 ==> tous les 4 semaines
- recurs_weekdays = 65 ==> (samedi=64 + dimanche=1)
- recurs_day et recurs_ordinal = 0 = = > non utilisé
De même, tous les 6 mois le premier vendredi du mois serait
- récurs = 3 = = > récurrence mensuelle
- recurs_interval = 6 ==> tous les 6 mois
- recurs_ordinal = 1 ==> sur la première occurrence
- recurs_weekdays = 32 ==> du vendredi
Rien de cette affaire d'avoir un champ qui signifie trois choses entièrement différentes en fonction de la valeur d'un autre champ.
Du côté de l'interface utilisateur, je laisse l'utilisateur spécifier une date, une heure de début, une heure de fin. Ils peuvent ensuite spécifier s'ils veulent un type de récurrence autre que none. Si c'est le cas, l'application étend la section pertinente de la page web pour donner à l'utilisateur les options requises pour les choses ci-dessus, ressemblant beaucoup aux options Outlook, sauf qu'il n'y a pas "tous les jours de la semaine" sous récurrence quotidienne( qui est redondant avec récurrence hebdomadaire sur tous les Lundi-vendredi), et il n'y S'il y a récurrence, j'exige également que l'utilisateur spécifie une date de fin dans l'année qui suit aujourd'hui (les utilisateurs le veulent de cette façon, et cela simplifie mon code) - je ne fais pas de récurrence sans fin ou " fin après les occurrences##."
Je stocke ces champs avec les sélections de l'utilisateur dans ma table d'événements et je les développe dans une table de planification qui contient toutes les occurrences. Cela facilite la détection de collision (je fais en fait une application de réservation d'installation) et l'édition d'occurrences individuelles ou la refactorisation d'occurrences futures.
Mes utilisateurs sont tous dans CST, et je remercie le bon Seigneur. C'est une simplification utile pour l'instant, et si à l'avenir la base d'utilisateurs va s'étendre au-delà de cela, alors je peux comprendre comment y faire face, comme une tâche bien séparée.
Mettre à jour Depuis que j'ai écrit ceci, j'ai ajouté l'occurrence quotidienne avec "chaque jour de la semaine". Nos utilisateurs ont eu un peu de mal à penser que vous pourriez utiliser la récurrence hebdomadaire pour les événements qui se déroulent du jeudi une semaine au mardi la semaine suivante et seulement en semaine. Il était plus intuitive pour eux d'avoir cela, même s'il y avait déjà une autre façon qu'ils pouvaient le faire.
J'ai pensé à cela aussi, bien que je ne l'ai pas implémenté mais ce sont mes pensées pour une solution simple.
Lors de la configuration d'un événement récurrent, demandez à l'utilisateur de spécifier la "date de fin" et de créer des événements individuels pour chacun d'eux (en fonction des options récurrentes). Parce que c'est un événement récurrent, définissez un "ID récurrent" unique pour chacun d'entre eux. Ce code sera ensuite utilisé pour marquer un événement récurrent et si vous modifiez un événement à venir, vous pouvez demander à l'utilisateur d'appliquer cette pour le reste des événements futurs en supprimant et en recréant les événements récurrents avec un nouvel "ID récurrent" qui différenciera également cet événement récurrent des événements précédents qui ont changé.
J'espère que cela a du sens et aimerait des commentaires.
J'enregistrerais les événements récurrents comme deux choses distinctes dans la base de données. Tout d'abord, dans une table d'événements, enregistrez chaque occurrence de l'événement. Deuxièmement, avoir des répétitions de tableau dans lequel vous enregistrez les détails que vous demandez pour configurer l'événement récurrent. Date de début, périodicité, nombre d'occurrences, etc.
Ensuite, vous pourriez penser à lier tout cela en mettant le PK des récurrences dans chacun des enregistrements d'événements en tant que FK. Mais une meilleure conception serait de normaliser la table des événements en deux tables, l'une qui est juste les barebones d'un événement, et l'autre qui a les détails, qui pourraient maintenant se référer à plusieurs événements. De cette façon, chaque enregistrement d'événement, récurrent ou non, a un FK au PK de la table eventdetails. Ensuite, dans eventdetails, enregistrez le PK des récurrences quelque part avec agenda, invités, etc. L'enregistrement de récurrence ne conduit rien. Par exemple, si vous voulez une liste de tous les événements récurrents, vous consultez eventdetails pour tous les événements avec un FK non null aux récurrences.
Vous devrez faire attention à synchroniser toutes ces choses, de sorte que vous insérez ou supprimez des événements lorsque les données de récurrence changent.
"mis à part toute autre chose"
Cela inclut-il "les exigences mêmes"?
" cela facilitera l'exportation vers d'autres applications Si vous le souhaitez."
Les exigences énoncées comprennent-elles "il doit être facile d'exporter les calendriers vers d'autres applications"? Mon impression était que le problème consistait uniquement à construire la première application .
Cela dit, ma propre réponse:
Vous devez vous limiter/votre utilisateur sur les types de "récurrence" votre système sera en mesure de soutenir. Et "tout ce qui précède" ou "aucune limitation" ne sera pas une réponse valide si vous/votre utilisateur voulez(s) se retrouver avec une application utilisable.