0

环境:
SQL CE
Windows Phone 7.5及以上
Visual Studio 2012更新3
示例:30个所有任务,10个今天任务,10个明天任务,10个过期任务

要求
一个待办应用,需要在首页显示3个数字,所有任务,今天任务,明天任务。

原始代码:

private Stopwatch sw=new Stopwatch();
using (TasksDataContext db = new TasksDataContext(TasksDataContext.DBConnectionString))
{
     sw.Start();
     var allTask = db.TasksItems.Where(t => t.Title != null && t.IsCompleted != true);
     System.Diagnostics.Debug.WriteLine( "allTask:"+sw.ElapsedMilliseconds.ToString());
     Taskamount = allTask.Count();

     var todayTask = db.TasksItems.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date & t.IsCompleted == false);
     System.Diagnostics.Debug.WriteLine("todayTask:" + sw.ElapsedMilliseconds.ToString());
     todayNumber = todayTask.Count();

     var tomorrowTask = db.TasksItems.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date.AddDays(1) & t.IsCompleted == false);
     System.Diagnostics.Debug.WriteLine("tomorrowTask:" + sw.ElapsedMilliseconds.ToString());
     sw.Stop();
     tomorrowNumber = tomorrowTask.Count();
}

后期代码:

private Stopwatch sw=new Stopwatch();
using (TasksDataContext db = new TasksDataContext(TasksDataContext.DBConnectionString))
{
     sw.Start();
     var allTask = db.TasksItems.Where(t => t.Title != null && t.IsCompleted != true);
     System.Diagnostics.Debug.WriteLine( "allTask:"+sw.ElapsedMilliseconds.ToString());
     Taskamount = allTask.Count();

     var todayTask = allTask.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date & t.IsCompleted == false);
     System.Diagnostics.Debug.WriteLine("todayTask:" + sw.ElapsedMilliseconds.ToString());
     todayNumber = todayTask.Count();

     var tomorrowTask = allTask.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date.AddDays(1) & t.IsCompleted == false);
     System.Diagnostics.Debug.WriteLine("tomorrowTask:" + sw.ElapsedMilliseconds.ToString());
     sw.Stop();
     tomorrowNumber = tomorrowTask.Count();
}

调试输出
原始:
第一次:
allTask​​:9
todayTask:165
tomorrowTask:221

第二次:
所有任务:10
今天任务:179
明天任务:233

第三次:
所有任务:14
今天任务:168
明天任务:225

第 4 次:
所有任务:8
今天任务:181
明天任务:236

第 5 次:
所有任务:8
今天任务:166
明天任务:221


最新:
第 1 次:
所有任务:9
今天任务:157
明天任务:216

第二次:
所有任务:8
今天任务:163
明天任务:219

第三次:
所有任务:8
今天任务:161
明天任务:216

第 4 次:
所有任务:8
今天任务:164
明天任务:222

第 5 次:
所有任务:9
今天任务:153
明天任务:210

为什么我修改代码
因为今天任务和明天任务是所有任务的子集。我认为重用 linq 查询变量将提高性能。结果显示了微小的提升。

让我感到困惑的是:
我阅读了 MSDN 中的 linq 部分,它说:

在 LINQ 中,查询的执行不同于查询本身。换句话说,您并没有仅仅通过创建查询变量来检索任何数据。

这让我想到了一个问题:为什么会快一点?根据MSDN所说:重用linq query不会提升性能反而会伤害性能。

当编译器运行以下代码时:

var todayTask = allTask.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date & t.IsCompleted == false);

它将执行 2 次操作,一个用于 allTask​​,一个用于 todayTask。但是当使用“db.taskitems.Where()”时,它只做一次操作。

我的问题
1. 为什么它更快?(编译器是否在编译时优化我的代码?)
2. 有没有更好的方法来提高速度?

4

1 回答 1

0

allTask由于查询 ( t => t.Title != null)中的额外条件,可能会出现这种加速。这不包括在todayTask和中tomorrowTask

为了加快速度,您可以尝试使用Count谓词并删除冗余条件:

var allTask = [...];
Taskamount = allTask.Count();
todayNumber = allTask.Count(t => t.DueDate != null && t.DueDate.Value.Date == DateTime.Now.Date);
tomorrowNumber = allTask.Count(t => t.DueDate != null && t.DueDate.Value.Date == DateTime.Now.Date.AddDays(1));

您也可以尝试GroupBy

var result = allTask.GroupBy(x => 1, x => x, (key, g) => new
{
    All = g.Count(),
    Today = g.Count(t => t.DueDate != null && t.DueDate.Value.Date == DateTime.Now.Date),
    Tomorrow = g.Count(t => t.DueDate != null && t.DueDate.Value.Date == DateTime.Now.Date.AddDays(1))
}).Single();

这应该对所有聚合进行一次查询,但我不知道是否所有 linq 驱动程序都支持它。

于 2013-10-14T07:10:08.733 回答