我正在做一个日历,为了让自己更容易,我打破了跨越数周的约会。
例如,1月1日至1月31日的时间跨度约为6周(我的日历总是42个单元-6乘7)。因此,我基本上可以将6行存储在我的数据库中。
但是,有些事情我确实要求我把所有这些行重新组合到一行中。例如,如果我想导出我的日历格式。
我的数据库中有一个名为bindingClassName的字段,所有这些行对这组任务都有相同的unquie,所以我能够轻松地获得所有的周。
// get all of the task rows by binding class name.
var found = plannerDb.Calendars.Where(u => u.UserId == userId && u.BindingClassName == bindingClassName)
.GroupBy(u => u.BindingClassName);
List<Calendar> allAppoingments = new List<Calendar>();
// go through each of the results and add it to a list of calendars
foreach (var group in found)
{
foreach (var row in group)
{
Calendar appointment = new Calendar();
appointment.AppointmentId = row.AppointmentId;
appointment.AllDay = row.AllDay;
appointment.BindingClassName = row.BindingClassName;
appointment.Description = row.Description;
appointment.EndDate = row.EndDate;
appointment.StartDate = row.StartDate;
appointment.Title = row.Title;
appointment.Where = row.Where;
appointment.UserId = row.UserId;
allAppoingments.Add(appointment);
}
}
// order
var test = allAppoingments.OrderBy(u => u.StartDate);
var firstAppointment = test.First();
var LastAppointment = test.Last();
Calendar newAppointment = new Calendar();
newAppointment.UserId = firstAppointment.UserId;
newAppointment.Description = firstAppointment.Description;
newAppointment.AllDay = firstAppointment.AllDay;
newAppointment.StartDate = firstAppointment.StartDate;
newAppointment.Title = firstAppointment.Title;
newAppointment.Where = firstAppointment.Where;
newAppointment.BindingClassName = firstAppointment.BindingClassName;
newAppointment.EndDate = LastAppointment.EndDate;
return newAppointment;
因此,基本上,这个大blob可以找到所有具有相同绑定名称的约会。然后,我遍历每一个,并将其变成一个Calendar对象,最后,一旦全部完成,我将获得第一条也是最后一条记录,以获得startDate和endDate。
所以我对linq不太在行,但是我不确定我是否可以在groupBy之后添加一些东西来做我想做的事情。
编辑
一旦我从用户那里得到所有的约会,我就尝试将所有的约会组合在一起。
所以到目前为止我有这个
我试过这样的方法。
var allApointments = calendar.GetAllAppointments(userId);
var group = allApointments.GroupBy(u => u.BindingClassName).Select(u => new Calendar()).ToList
我本来希望它能自动填充每一组,但它没有。所以我不确定是否不需要再来一次。
编辑@ admin
嗨,谢谢你解释分类和分组。你是怎么解释这件事的,尽管看上去这两种方法都管用。
就像你得到第一次和最后一次约会的代码一样,效果很好,做了我想做的事情。
我认为分组可能是有效的,因为最终,尽管我希望有一行具有第一条记录的开始日期和最后一条记录的结束日期,但所有其他信息都是相同的。
因此,我不知道是否会更难写代替或什么,但就像我说的,你的查询做我想做的。
但是,该查询是在单一基础上使用的。就像我只在用户单击查看日历上的约会时才使用该查询一样。通过单击约会,我可以获得有关该约会的所有信息,这是我需要查看任务是否跨越多天的地方,并确定约会何时开始和何时结束。
现在,我需要另一个查询,我认为如果我能够根据您的解释对它们进行分组,就更好了,它将产生一行。我认为这是因为我想从那个用户导出表中的所有记录。
因此,如果我按绑定名称将它们排序为一个连续块,我仍然需要一些循环,这些循环遍历所有记录,获取第一个和开始日期。所以,如果我能一次把它分组,最后的结果将是每组绑定名称的一个记录,它将有第一个开始日期和第一个和最后一个记录的最后结束日期会更好。
发布于 2010-01-04 21:24:18
如果没有实际使用组,为什么要将约会分组?看起来你只是在单独使用它们。在任何情况下,您都已经在筛选BindingClassName
子句中单个值上的行,因此最终只能得到1(或0)组。
您可以将这一系列foreach
循环重写为Select
和ToList()
,如下所示:
var allAppointments =
plannerDb.Calendars.Where(
row => row.UserId == userId &&
row.BindingClassName == bindingClassName).OrderBy(
row => row.StartDate).Select(
row => new Calendar()
{
AppointmentId = row.AppointmentId,
AllDay = row.AllDay,
BindingClassName = row.BindingClassName,
Description = row.Description,
EndDate = row.EndDate,
StartDate = row.StartDate,
Title = row.Title,
Where = row.Where,
UserId = row.UserId
}).ToList();
这会按你想要的顺序把完整的清单还给你。然而,我很好奇,当你看起来只对第一次和最后一次约会感兴趣的时候,你为什么要检索整个列表。你可以这样做:
var baseQuery =
plannerDb.Calendars.Where(
row => row.UserId == userId &&
row.BindingClassName == bindingClassName);
var first = baseQuery.OrderBy(row => row.StartDate).First();
var last = baseQuery.OrderByDescending(row => row.StartDate).Select(
row => row.EndDate).First();
return new Calendar()
{
AppointmentId = first.AppointmentId,
AllDay = first.AllDay,
BindingClassName = first.BindingClassName,
Description = first.Description,
EndDate = last,
StartDate = first.StartDate,
Title = first.Title,
Where = first.Where,
UserId = first.UserId
});
这将产生与现在相同的输出。不过,如果这正是你想要的,我会提出疑问。假设你有两个约会:
使用这个(和您的)逻辑,您将获得1月7日的结束日期,因为约会2有更大的开始日期,但约会1实际上在稍后结束。我建议将第二个查询改为:
var last = baseQuery.OrderByDescending(row => row.EndDate).Select(
row => row.EndDate).First();
这将给你最大的结束日期,我认为这是你真正想要的。
编辑
我认为你犯了(非常常见的)错误,把分组和排序混淆在一起。当您说要“根据绑定名称对约会进行分组”时,听起来您需要一个完整的约会列表,并且您希望这些约会的安排方式是,所有具有特定绑定名称的约会都形成一个连续块。如果是这样的话,您希望按照绑定名称来排序列表,而不是对它们进行分组。分组使用整个列表并生成每组一行的子句,并允许您对其余的列执行聚合功能。例如,假设我根据绑定名称对约会进行分组。这意味着我的结果集将包含每一个绑定名称的一行,然后我可以执行类似于查找最大开始日期或结束日期之类的事情;更正式地说,您可以指定聚合操作,这是接受一组数据(即开始日期列表)并返回单个数据(即最大开始日期)的操作。
除非我误解了,听起来你仍然想要检索所有的个人作业,你只是想要它们按绑定名称排列。如果是这样的话,只要OrderBy(row => row.BindingName)
就行了。此外,您可能希望避免使用“组”一词,因为人们会认为您指的是我前面描述的那种分组。
发布于 2010-01-06 04:48:53
作为一个不涉及linq的侧重点,您看过AutoMapper吗?我目前正在使用它来填充linq中的数据对象,我发现它对于摆脱只映射到dtos的大量代码非常有用。它不会使代码的查询部分变得更短,但会减少:
return new Calendar()
{
AppointmentId = first.AppointmentId,
AllDay = first.AllDay,
BindingClassName = first.BindingClassName,
Description = first.Description,
EndDate = last,
StartDate = first.StartDate,
Title = first.Title,
Where = first.Where,
UserId = first.UserId
});
至:
return Mapper.Map(first,new Calendar{EndDate = last});
https://stackoverflow.com/questions/2004291
复制相似问题