我正在尝试在C#中开发一个与调度程序和日历相关的事件应用程序,其关键要求是表示数据库中的重复事件。 在数据库中表示重复事件的最佳方法是什么?
更多详情:
在创建活动时,我也向某些用户发送邀请,并且只允许被邀请者在指定的窗口(会议持续时间)内登录会议,或者当被邀请者尝试登录时可以拒绝登录,会议开始前5分钟。
答案 0 :(得分:38)
SQL Server中的sysjobs,sysjobsschedule和sysschedules表可以很好地完成这项工作。我不会重新发明轮子,我只是复制他们的设计。
以下是sysschedules
<强> freq_type 强>
此计划的作业运行频率。
1 =仅一次
4 =每日
8 =每周
16 =每月
32 =每月,相对于freq_interval
64 = SQL Server代理服务启动时运行
128 =计算机空闲时运行
<强> freq_interval的强>
作业执行的天数。取决于freq_type的值。默认值为0,表示freq_interval未使用。 freq_type对freq_interval的影响
1(一次)freq_interval未使用(0)
4(每天)每个freq_interval天
8(每周)freq_interval是以下一项或多项:1 =周日2 =周一4 =周二8 =周三16 =周四32 =周五64 =周六
16(每月)在该月的freq_interval日
32(每月,相对)freq_interval是以下之一:1 =星期日2 =星期一3 =星期二4 =星期三5 =星期四6 =星期五7 =星期六8 =第9天=工作日10 =周末
64(SQL Server代理服务启动时启动)freq_interval未使用(0)
128(计算机空闲时运行)freq_interval未使用(0)
<强>的freq_subday_type 强>
freq_subday_interval的单位。可以是以下值之一: 值描述(单位)
1在指定时间
2秒
4分钟
8小时
<强> freq_subday_interval 强>
每次执行作业之间发生的freq_subday_type周期数。
<强> freq_relative_interval 强>
当每个月发生freq_interval时,如果freq_interval是32(每月相对)。可以是以下值之一:
0 = freq_relative_interval未使用
1 =第一次
2 =第二
4 =第三
8 =第四次
16 =最后
<强> freq_recurrence_factor 强>
计划执行作业之间的周数或月数。 freq_recurrence_factor仅在freq_type为8,16或32时使用。如果此列包含0,则freq_recurrence_factor未使用。
答案 1 :(得分:24)
好吧,要存储重复规则本身,你可以使用RFC 5545的缩减版本(我真的建议你大幅削减它)。除此之外,如果您愿意,可以轻松导出到其他应用程序中。
在做出决定之后,对于数据库方面,您需要确定是否要存储事件的每次出现,或者仅为重复事件存储一条记录,将其扩展为当你需要的时候。显然,当您已经扩展了所有内容时,查询数据库要容易得多 - 但这使得维护变得更加棘手。
除非你想写一些非常复杂的SQL,这可能很难测试(并且你需要很多的单元测试用于各种极端情况)我建议你制作数据库它本身相对“愚蠢”,并且用Java或C#等语言编写大部分业务逻辑 - 当然,这些逻辑可以嵌入到存储过程中,具体取决于您的数据库。
您需要问自己的另一件事是,您是否需要处理事件中的例外 - 一系列更改时间/位置等事件。
我有一些日历方面的经验(我去年大部分时间都在通过ActiveSync处理Google Sync的日历位),我应该警告你事情变得复杂真的很快。任何你认为“超出范围”的东西都是一种祝福。特别是,您需要在多个时区工作吗?
哦,最后 - 当您使用日历操作进行实际算术时,要非常非常小心。如果您要使用Java,请使用Joda Time而不是内置的Calendar
/ Date
类。他们会帮助你很多。
答案 2 :(得分:7)
这里接受的答案太复杂了。例如,如果事件每5天发生一次,则5存储在freq_interval中,但如果它每5周发生一次,则5存储在freq_recurrence中。最大的问题是freq_interval意味着三种不同的东西,具体取决于freq_type的值(每日复发的发生次数,每月复发的日期,或每周或每月相对的星期几)。此外,当不需要且不太有用时,使用1,2,4,8 ...类型序列。例如,freq_relative_interval只能是&#34;其中一个&#34; 可能的值。这与一个下拉框或单选按钮类型输入对齐,而不是一个复选框类型输入,可以选择多个选项。对于编码和人类可读性,这个序列会妨碍使用1,2,3,4 ...更简单,更有效,更合适。最后,大多数日历应用程序都不需要子日间隔(一天中多次发生的事件 - 每隔几秒,几分钟或几小时)。
但是,说了这些,这个答案确实帮助我改进了我对自己的看法。在将其与其他文章混合并匹配后,从我在Outlook日历界面和其他一些来源中看到的内容后,我想出了这个:
<强>复发强>
0 =没有复发
1 =每日
2 =每周
3 =月
<强> recurs_interval 强>
这是复发之间的多少个时期。如果事件每5天重复一次,那么这将是5,重复将有1.如果事件每2周重复一次,那么将有2和重复将有a 2.
<强> recurs_day 强>
如果用户选择每月类型重复,则在该月的某一天(例如:10日或14日)。这个日期。如果用户未选择每月或特定日期重复,则该值为0。否则,该值为1到31。
<强> recurs_ordinal 强>
如果用户选择了每月类型的重复,而是一个序数类型的日(例如:第一个星期一,第二个星期四,上周五)。这将具有该序数。如果用户未选择此类重复,则该值为0
1 =第一
2 =第二
3 =第三
4 =第四
5 =最后
<强> recurs_weekdays 强>
对于每周和每月 - 有序复发,这将存储复发发生的工作日。
1 =星期日
2 =周一
4 =星期二
8 =星期三
16 =星期四
32 =星期五
64 =星期六
所以,例如:
因此,星期六和星期日每4周就会
同样,每个月的第一个星期五每6个月就会
根据另一个领域的价值,这个业务没有任何意义,这意味着三个完全不同的东西。
在用户界面方面,我让用户指定日期,开始时间,结束时间。然后,他们可以指定是否需要除非之外的某种类型的重复。如果是这样,应用程序会扩展网页的相关部分,为用户提供上述内容所需的选项,看起来很像Outlook选项,除了没有&#34;每个工作日&#34;每日复发(这是多余的,每周一次复发每周复发),并且没有每年复发。如果有重复发生,那么我还要求用户指定一个在今天一年内的结束日期(用户希望这样,并简化我的代码) - 我不会无休止复发或&# 34;在##次出现后结束。&#34;
我将这些字段与用户选择存储在我的事件表中,然后在具有所有事件的计划表中展开它。这有利于碰撞检测(我实际上正在进行设施预约申请)和编辑个别事件或重构未来事件。
我的用户都在CST,我感谢好主。现在这是一个有用的简化,如果将来用户群将扩展到那个以上,那么我可以弄清楚如何处理它,作为一个完全分离的任务。
<强>更新强> 自从我第一次写这篇文章以来,我确实每天都会添加&#34;每个工作日#34;我们的用户有一段时间的困难,他们认为您可以使用每周重复发生从周四一周到下周二周二发生的事件,并且仅在工作日发生。即使已经有另一种方式可以做到这一点,他们也更直观了。
答案 3 :(得分:0)
我一直在考虑这个问题,虽然还没有实现,但这些是我对一个简单解决方案的想法。
设置重复发生的事件时,让用户指定“结束日期”并为每个事件创建单独的事件(基于重复选项)。因为它是一个反复出现的事件,所以为每个事件设置一个独特的“经常性ID”。然后,此ID将用于将事件标记为重复发生,如果您更改将来的事件,则可以通过删除并使用新的“周期性ID”重新创建重复事件来提示用户将此应用于其余未来事件。也会将此重复事件与之前已发生变化的事件区分开来。
希望这是有道理的,并希望得到任何评论。
答案 4 :(得分:0)
我会将重复发生的事件记录为数据库中的两个独立事物。首先,在事件表中,记录事件的每个事件。其次,有一个重复表,您可以在其中记录您要求设置重复事件的详细信息。开始日期,周期,出现次数等。
然后你可能会想到将重复的PK作为FK放入每个事件记录中。但更好的设计是将事件表规范化为两个表,一个表只是事件的准系统,另一个表示详细信息,现在可以引用多个事件。这样,每个事件记录,无论是否重复,都有一个FK到eventdetails表的PK。然后在事件详细信息中,记录重复的PK以及议程,被邀请者等。重复记录不会驱动任何事情。例如,如果您想要一个包含所有重复事件的列表,请查看具有非空FK的所有事件的事件详细信息以重复发生。
您需要小心同步所有这些内容,以便在重复数据更改时插入或删除事件。
答案 5 :(得分:-4)
“除了其他任何事情”
这包括“非常要求”吗?
“如果您愿意,可以轻松导出到其他应用程序中。”
所述要求是否包括“将日历导出到其他应用程序必须很容易”?我的印象是,问题仅在于构建 FIRST 应用程序。
说,我自己的回答:
您需要限制自己/您的用户使用系统能够支持的“重新加速”类型。如果您/您的用户希望以最终的可用应用程序结束,“以上所有”或“无限制”将不是有效答案。