我怎样才能做一次"一次击中"具有可空值的Linq查询?

时间:2014-04-28 14:20:54

标签: c# linq

我有以下课程:

public class MyTrelloCard
{
    ...
    public DateTime? completed { get; set; }
    public Decimal? estHours { get; set; }
    public bool complete { get; set; }
}

...我想查询完成日期中每个日期的estHours数量。这些必须是可以为空的值,因为并非每张卡都已完成,并且并非每张卡都有估计的小时数。

目前我必须运行两个查询。第一个:

List<burnDownData> bData = (from c in cards
                            where c.complete
                            group c by new
                            {
                                date = Convert.ToDateTime(c.completed).Date
                            } into g
                            select new burnDownData
                            {
                                date = g.Key.date,
                                completedHours = g.Sum(x=>x.estHours) ?? 0
                            }).ToList();

返回已完成的所有卡片。

第二个用于迭代开始和结束时段之间的所有日期,并累计累计完成的小时数:

for (DateTime d = start; d.Date <= end; d = d.AddDays(1))
{
    if ((d.DayOfWeek >= DayOfWeek.Monday) && (d.DayOfWeek <= DayOfWeek.Friday))
    {
        List<C> values = new List<C>();

        Decimal xx = (from b in bData
                      where b.date.Date == d
                      select b.completedHours).SingleOrDefault();

        total = total + xx;

        values.Add(new C { v = d.ToString("d MMM") });
        values.Add(new C { v = total.ToString() });

        myRows.Add(new Row { c = values });
    }
}

但这似乎效率低下。有可能直接这样做吗?即取代循环的这一部分:

Decimal xx = (from b in bData
              where b.date.Date == d
              select b.completedHours).SingleOrDefault();

直接查询cards数据?

2 个答案:

答案 0 :(得分:2)

解释您的问题:

  

我想在完成的每个日期查询estHours的数量   日期。这些必须是可以为空的值,因为并非每张卡都完成,   并非每张卡都有估计的小时数加入

... as&#34;我试图获取每个completed日期实例的估计小时数之和,并希望允许空completed和{{1} }值&#34;。
您可以在Where子句中包含null检查:

estHours

例如:

var x = cards.Where(c => c.completed != null )
    .GroupBy(c => c.completed, (key, group) => new
    {
        dateComp = key.Value,
        totEstHrs = group.Sum(i => i.estHours)
    });
x.ToList().ForEach(
    item => Debug.Print("{0:MM/dd/yyyy} {1}", item.dateComp, item.totEstHrs));

产地:

  

04/28/2014 12

     

04/29/2014 3

修改 要仅对日期部分进行分组(省略时间戳),您可以对ToShortDateString()值进行分组:

List<MyTrelloCard> cards = new List<MyTrelloCard>() {
    new MyTrelloCard() { completed = new DateTime(2014, 4, 28), estHours = 5,    complete = true },
    new MyTrelloCard() { completed = null,                      estHours = 5,    complete = false },
    new MyTrelloCard() { completed = null,                      estHours = null, complete = true },
    new MyTrelloCard() { completed = new DateTime(2014, 4, 28), estHours = 7,    complete = false },
    new MyTrelloCard() { completed = new DateTime(2014, 4, 29), estHours = null, complete = false },
    new MyTrelloCard() { completed = new DateTime(2014, 4, 29), estHours = 3,    complete = false },
};

答案 1 :(得分:1)

啊 - 所以你想要在你的范围内的每个工作日输入一个条目,即使那天没有数据。在这种情况下,建立一系列符合条件的日子,并分组加入您的卡片。

以下是:

var start = DateTime.Today;
var end = start.AddDays(14);

var cards = new[]{new {complete = true, completed = (DateTime?)DateTime.Now, estHours = new decimal?(3)} };

var days = Enumerable.Range(0, end.Subtract(start).Days)
.Select(x => start.AddDays(x))
.Where(x => !new []{DayOfWeek.Saturday,DayOfWeek.Sunday}.Contains(x.DayOfWeek));

var results = from d in days
              join c in cards on d equals c.completed.GetValueOrDefault().Date
              into cGrp
              select new {d, completedHours = cGrp.Sum(x => x.estHours)};

当然您不需要var cards =行,因为您已拥有自己的源代码!

修改 - 将一天的所有时间戳分组为1天。