如果您最常阅读事件,并且不介意节省一点额外成本,则可以选择根据规则将事件具体化到新表中。如果您愿意,可以根据规则清除并重新生成该表,或者根据需要选择性地重新填充该表。
保存后的事件 1 将创建一个条目,EventID:1
保存后的事件 2 将为与 DOW 属性匹配的日期范围创建条目,EventID:2
事件 3 会做同样的事情,但它的日期范围/DOW,EventID:3
如果需要,您可以使用一些花哨的 LINQ 来计算要添加的行,但最终结果是您需要物理实例行以便真正轻松查询。
更新事件时,您可以简单地删除该 EventID 的所有行并根据更改重新创建它们。
鉴于上述情况,您的读取操作可能很简单:
EventInstances.Where(i => i.Date >= startDate && i.Date <= endDate);
相反,如果您想要缓慢/复杂的读取和快速写入,则每次读取时都需要生成此内存映射。
更新:一些代码来说明我的意思
填充表的逻辑与您可以用来创建内存表的逻辑完全相同:
// slightly updated Event class
public class Event
{
public int ID { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public DayOfWeek[] DayOfWeekList { get; set; }
public string Title { get; set; }
}
var startDate = new DateTime(2013, 9, 1);
var endDate = new DateTime(2013, 9, 16);
var totalDays = (int)endDate.Subtract(startDate).TotalDays + 1;
// sample data, including a 4th event starting a while ago with no end date
var events = new List<Event> {
new Event { ID = 1, Title = "Event 1", StartDate = new DateTime(2013, 9, 15), EndDate = new DateTime(2013, 9, 15), DayOfWeekList = new[] { DayOfWeek.Sunday } },
new Event { ID = 2, Title = "Event 2", StartDate = new DateTime(2013, 9, 15), EndDate = new DateTime(2013, 9, 16), DayOfWeekList = new[] { DayOfWeek.Sunday, DayOfWeek.Monday } },
new Event { ID = 3, Title = "Event 3", StartDate = new DateTime(2013, 9, 1), EndDate = new DateTime(2013, 9, 30), DayOfWeekList = new[] { DayOfWeek.Tuesday, DayOfWeek.Thursday } },
new Event { ID = 4, Title = "Event 4", StartDate = new DateTime(2013, 1, 1), EndDate = null, DayOfWeekList = new[] { DayOfWeek.Wednesday } },
};
var eventsInRange = events
.Where(e => e.StartDate <= endDate)
.Where(e => (e.EndDate == null || e.EndDate.Value >= startDate ))
// if you are getting from the database, force this data to be
// retrieved since the following section would not work with the DB
.AsEnumerable();
var daysInRange = Enumerable
.Range(0, totalDays)
.Select(i => startDate.AddDays(i));
var eventInstances = daysInRange
.SelectMany(d => eventsInRange
.Where(e => e.EndDate == null || d <= e.EndDate.Value)
.Where(e => d >= e.StartDate)
.Where(e => e.DayOfWeekList.Contains(d.DayOfWeek))
.Select(e => new { Date = d, Day = d.DayOfWeek, Event = e }));
如果您想用这些数据填充表格以便于查询,只需根据合理的设置开始日期和结束日期(例如,1 年前开始,2 年结束时间)。
如果您想在更新后仅为一个事件重新填充,只需删除该事件 ID 的所有记录并将其限制eventsInRange
为仅更新事件。