我正在尝试用C#开发一个依赖于调度器和日历的事件应用程序,它的一个关键需求是在数据库中表示重复发生的事件。在数据库中表示重复事件的最佳方式是什么?
更多详细信息:
在创建事件时,我还向某些用户发送邀请,并且应该只允许被邀请者在指定的窗口(会议持续时间)内登录会议,或者在被邀请者尝试登录时拒绝登录,例如,在预定的会议开始前5分钟。
发布于 2009-10-16 18:34:07
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)
每freq_interval天4天(每天)
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_type为8、16或32时才使用freq_recurrence_factor。如果此列包含0,则未使用freq_recurrence_factor。
发布于 2009-10-16 18:39:17
嗯,为了存储递归规则本身,您可以使用RFC 5545的精简版本(我真的建议您大幅削减它)。抛开其他事情不谈,如果你愿意的话,这将使你可以很容易地导出到其他应用程序中。
做出决定后,对于数据库端,您需要确定是要存储每个事件的发生,还是只存储重复事件的一条记录,并在需要时展开它。显然,当您已经扩展了所有内容时,查询数据库要容易得多--但这会使维护变得更加棘手。
除非您想要编写一些很难测试的复杂SQL (并且您需要对各种特殊情况进行大量的单元测试),否则我建议您使数据库本身相对“愚蠢”,并使用Java或C#之类的语言编写大部分业务逻辑-当然,这两种语言都可以嵌入到存储过程中,具体取决于您的数据库。
你需要问自己的另一件事是,你是否需要处理事件的异常-一系列事件中的一个事件,改变时间/地点等。
我有一些使用日历的经验(我在过去一年的大部分时间里都在通过ActiveSync处理Google Sync的日历),我应该警告您,事情变得非常复杂。任何你认为“超出范围”的东西都是一种福气。特别是,您是否需要在多个时区工作?
哦,最后,当你使用日历操作进行实际的算术运算时,要非常非常小心。如果您打算使用Java,请使用Joda Time而不是内置的Calendar/Date类。他们会帮到你很多。
发布于 2015-06-02 01:31:04
这里公认的答案太复杂了。例如,如果事件每5天发生一次,则5存储在freq_interval中,但如果它每5周发生一次,则5存储在freq_recurrence中。最大的问题是,根据freq_type的值,freq_interval表示三种不同的含义(每天重复出现的天数,每月重复出现的天数,或者每周或每月相对的星期几)。还有,1,2,4,8...类型序列在不必要且不太有用的情况下使用。例如,对于可能的值,freq_relative_interval只能是“”。这与下拉框或单选按钮类型的输入排列在一起,而不是复选框类型的输入,其中可以选择多个选项。为了编码,为了人类的可读性,这个序列妨碍了使用1,2,3,4……更简单,更高效,更合适。最后,大多数日历应用程序不需要子日间隔(事件在一天中多次发生-每隔几秒、几分钟或几小时)。
但是,话虽如此,这个答案确实帮助我完善了我对如何做到这一点的想法。在将它与其他文章混合并匹配之后,根据我在Outlook日历界面和其他一些来源中看到的内容,我得出了以下结论:
重现
0=no循环
1=daily
2=weekly
3=monthly
recurs_interval
这是两次递归之间的周期数。如果事件每5天重现一次,则这将是5, recurs 将是1。如果事件每2周重现,这将是2, recurs 将是2。
recurs_day
如果用户选择了每月类型重复,则在该月的给定日期(例如:10号或14号)。这上面有日期。如果用户未选择每月或特定月份的某一天重复,则该值为0。否则,该值为1到31。
recurs_ordinal
如果用户选择的是每月类型的重复,而是一天的顺序类型(例如:第一个星期一、第二个星期四、上周五)。这将包含该序数。如果用户未选择此类型的重复,则该值为0。
1=first
2=second
3=third
4=fourth
5=last
recurs_weekdays
对于每周和每月顺序的重现,它存储重现发生的工作日。1=Sunday
2=Monday
4=Tuesday
8=Wednesday
16=Thursday
32=Friday
64=Saturday
So,示例:
所以,每4周的周六和周日
循环周期=2周recurrence
同样,每6个月的第一个星期五将是
每个月循环=3个月recurrence
这与拥有一个字段的意义完全不同的事务无关,这取决于另一个字段的值。
在用户界面方面,我让用户指定日期、开始时间和结束时间。然后,他们可以指定是否需要none以外的递归类型。如果是这样,应用程序扩展网页的相关部分,为用户提供上面的内容所需的选项,看起来很像Outlook选项,除了在每日重复下没有“每个工作日”(这是多余的,每个星期一到星期五每周重复),也没有每年的重复。如果存在重复,我还要求用户指定一个离今天不超过一年的结束日期(用户希望这样做,它简化了我的代码)--我不做无休止的重复或“在##发生后结束”。
我将这些字段与用户选择一起存储在我的事件表中,并将其展开到包含所有匹配项的明细表中。这有助于冲突检测(我实际上正在做一个设施预订应用程序)和编辑单个实例或重构未来实例。
我的用户都在CST,感谢上帝。就目前而言,这是一个有用的简化,如果将来用户基础将扩展到更高的水平,那么我可以弄清楚如何处理它,作为一个独立的任务。
更新自从我第一次写这篇文章以来,我确实添加了“每个工作日”的日常事件。我们的用户有一点困难,认为您可以使用Weekly recurrence来处理从周四、一周到下一周发生的事件,而且只在工作日发生。对他们来说,这样做更直观,即使他们已经有了另一种方法。
https://stackoverflow.com/questions/1579638
复制相似问题