在数据库中表示“循环事件”的最佳方式是什么?
我正在尝试在C#中开发一个依赖于日程表和日历的事件应用程序,对此,一个关键的要求是在数据库中表示循环事件。 在数据库中表示重复事件的最佳方式是什么?
更多细节:
在创build活动的同时,我也向特定的用户发送邀请,被邀请者只能在指定的窗口(会议时间)内login到会议,或者在被邀请者试图login的时候,会议的预定开始。
SQL Server中的sysjobs , sysjobsschedule和sysschedules表格在这方面做得非常好。 我不会重新发明轮子,我只是复制他们的devise。
这里是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_intervaldate
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未使用。
那么,为了存储重复规则本身,你可以使用RFC 5545的削减版本(我真的build议你把它大大减less)。 除此之外,如果您愿意,可以轻松导出到其他应用程序。
做出这个决定之后,对于数据库端,您需要确定是要存储事件的每个事件,还是只存储一个重复事件的logging,并在需要时扩展它。 显然,当你已经扩展了所有的东西时,查询数据库相当容易 – 但是这使得维护变得更加困难。
除非你喜欢写一些相当复杂的SQL,这可能很难testing(你会想要对各种各样的angular落情况进行大量的unit testing),我build议你让数据库本身相对“愚蠢”,写大部分的像Java或C#这样的语言中的业务逻辑 – 当然,这两种语言中的任何一种都可以embedded到存储过程中,这取决于您的数据库。
你需要问自己的另一件事是你是否需要处理事件的例外 – 一个系列中的一个事件改变时间/地点等。
我有一些日历的经验(我去年的大部分时间都是通过ActiveSync在Google Sync的日历位置上工作的),我应该警告你事情会变得非常迅速。 任何你认为“超出范围”的东西都是福气。 特别是,你需要在多个时区工作吗?
哦,最后 – 当你用日历操作进行实际算术时,要非常小心。 如果您要使用Java, 请使用Joda Time而不是内置的Calendar
/ Date
类。 他们会帮助你很多。
这里接受的答案太复杂了。 例如,如果事件每5天发生一次,则5存储在freq_interval中,但如果每5周发生一次,则5将存储在freq_recurrence中。 最大的问题是,freq_interval意味着三种不同的事情,取决于freq_type的值(每日重复出现的天数,每月重复出现的月份的天数,或每周或每月相对的一周的天数)。 另外,1,2,4,8 …types的序列在没有必要和不太有用的情况下使用。 例如,freq_relative_interval只能是“可能的值之一” 。 这与下拉框或单选buttontypesinputalignment,而不是checkboxtypesinput,其中可以select多个select。 为了编码,并为了人类的可读性,这个序列阻碍,只使用1,2,3,4 …更简单,更高效,更合适。 最后,大多数日历应用程序不需要间隔时间间隔(事件在一天中多次发生 – 每隔几秒钟,几分钟或几小时)。
但是,这样说,那个答案确实帮助我改进了我的想法。 在与其他文章混合搭配之后,从我在Outlook日历界面和其他一些资源中看到的东西,我想出了这个:
复发
0 =不复发
1 =日常
2 =每周
3 =每月
recurs_interval
这是复发之间的多less时间。 如果事件每5天重复一次,则会有5次,而且会有1次重复。如果事件每2周重复一次,则会有2次,而且会出现 2次重复 。
recurs_day
如果用户在每个月的特定日子(例如10日或14日)select月度types重现。 有这个date。 如果用户没有select每月或特定的月份重复,则值为0。 否则值为1到31。
recurs_ordinal
如果用户select每月types的重复,而是一个序号types的一天(例如:第一个星期一,第二个星期四,最后一个星期五)。 这将有那个序号。 如果用户没有select这种types的重复,则该值为0。
1 =第一
2 =第二
3 =第三
4 =第四
5 =最后
recurs_weekdays
对于每周和每月的有序重复,这存储重复发生的平日。 1 =星期日
2 =周一
4 =星期二
8 =星期三
16 =周四
32 =星期五
64 =星期六
所以,星期六和星期天每4周就会有一次
recurs = 2,recurs_interval = 4,recurs_weekdays = 65(64 + 1)
同样的,每个月的第一个星期五的三个月都是
recurs = 3,recurs_interval = 3,recurs_ordinal = 1,recurs_weekdays = 32
没有一个领域的业务,这意味着三个完全不同的事情取决于另一个领域的价值。
在用户界面方面,我让用户指定一个date,开始时间,结束时间。 然后他们可以指定他们是否想要一种types的重复而不是没有。 如果是这样的话,应用程序扩大了网页的相关部分,给用户上面的东西所需的选项,看起来很像Outlook的选项,除了每天重复下没有“每个工作日”(这是多余的每个星期一每周复发),并且不存在每年的复发。 如果再次发生,那么我还要求用户指定一个在今天一年内的结束date(用户需要这样做,这简化了我的代码) – 我不会做无止境的重复发生或“在# #发生了“。
我将这些字段与用户select一起存储在我的事件表中,并将其展开到一个包含所有事件的日程表中。 这有利于碰撞检测(我实际上正在做一个设施预订应用程序)和编辑单个事件或重构未来的事件。
我的用户都在科技委,我感谢那个好主。 这对于现在来说是一个有用的简化,如果将来用户基础将会扩展到超越这个范围,那么我可以弄清楚如何处理它,这是一个很好的分离任务。
自从我第一次写这个,我每天添加“每个工作日”。 我们的用户有点难以想象,您可以使用每周重复发生从星期四到星期二发生的事件,并且仅在星期几发生。 对于他们来说,这是更直观的,即使已经有另一种方式可以做到这一点。
我也一直在想这个,虽然还没有实现,但这些是我的一个简单的解决scheme的想法。
当设置一个重复发生的事件时,让用户指定“结束date”并为每个事件创build单独的事件(根据重复选项)。 因为它是一个反复发生的事件,请为每个事件设置一个唯一的“重复的ID”。 这个ID将被用来标记一个事件为循环,如果你改变了一个未来的事件,你可以通过删除和重新创build一个新的“循环ID”的循环事件,提示用户将其应用到未来事件的其余事件也会将这个反复发生的事件与先前发生的变化区分开来。
希望这是有道理的,并希望有任何意见。
我会logging在数据库中的循环事件作为两个单独的事情。 首先,在事件表中logging事件的每一次发生。 其次,有重复表格,其中logging您要求设置重复事件的详细信息。 开始date,周期性,发生次数等
那么你可能会想到将所有事件logging中的重复PK作为一个FK放在一起。 但是更好的devise是将事件表标准化为两个表格,一个是事件的准系统,另一个是具体细节,现在可以指多个事件。 这样,每个事件logging,不pipe是否重复,都有一个FK到事件详细表的PK。 然后在事件细节中,logging重复发生的PK与议程,被邀请者等。重现logging不驱动任何东西。 例如,如果您想要所有周期性事件的列表,则可以查看所有具有非空FK的事件的事件细节来重现。
您需要小心地同步所有这些事情,以便在重复数据更改时插入或删除事件。
“除了别的东西”
这是否包括“非常要求”?
“如果你愿意的话,这样可以很容易地导出到其他应用程序中。”
所述的要求是否包括“将日历导出到其他应用程序很容易”? 我的印象是,问题仅仅是build立FIRST应用程序。
那就说,我自己的回应:
您需要限制自己/您的用户在系统将能够支持的“重复性”的types。 如果你/你的用户想要结束一个可用的应用程序,“以上所有”或“无限制”将不是一个有效的答案。