2011-06-17 91 views
6

我想从下面的方法使用EntityFramework和Linq获得总记录数。返回计数很慢。Linq选择语句慢时得到COUNT

public static int totalTracking(int id) 
{ 
    using (var ctx = new GPEntities()) 
    { 
     var tr = ctx.Tracking 
        .Where(c => c.clientID == Config.ClientID) 
        .Where(c => c.custID == id) 
        .Where(c => c.oOrderNum.HasValue) 
        .ToList(); 
     return tr.Count(); 
    }   
} 
+1

继承人一个办法,加快步伐,将查询合并为一个。我刚刚读了一篇关于这个的文章。 http://msmvps.com/blogs/jon_skeet/archive/2011/06/16/linq-to-objects-and-the-performance-of-nested-quot-where-quot-calls.aspx?utm_source=feedburner&utm_medium = feed&utm_campaign = Feed%3A + JonSkeetCodingBlog +%28Jon + Skeet%27s +编码+博客%29 – m4tt1mus 2011-06-17 00:08:04

回答

10

可以显著简化查询:

using (var ctx = new GPEntities()) 
{ 
    return ctx.Tracking 
     .Where(c => c.clientID == Config.ClientID) 
     .Where(c => c.custID == id) 
     .Where(c => c.oOrderNum.HasValue) 
     .Count(); 
} 

当你调用ToList这将触发物化,所以查询将被发布到数据库和所有列将被检索。实际的计数会发生在客户端。

如果你只是Count,没有ToList它会发出查询,当你打电话Count和服务器将返回一个数字,而不是一个表。

这不是性能这个关键,但我认为代码看起来有点不漂亮,很多Where

using (var ctx = new GPEntities()) 
{ 
    return ctx.Tracking 
     .Where(c => 
      c.clientID == Config.ClientID && 
      c.custID == id && 
      c.oOrderNum.HasValue) 
     .Count(); 
} 

甚至

using (var ctx = new GPEntities()) 
{ 
    return ctx.Tracking 
     .Count(c => 
      c.clientID == Config.ClientID && 
      c.custID == id && 
      c.oOrderNum.HasValue); 
} 
+0

Man - 我刚才看到.ToList() - 谢谢!您的代码正在工作 – 2011-06-17 00:11:21

+0

我想通过讨论它没有什么见解,但我更喜欢在Where-lambdas中不使用复合AND表达式。我发现当你可以做一个shift + del或添加一个新行时,它可以更容易地添加/删除条件,并且它可以更容易地区分未实现的谓词。 – kai 2016-02-21 17:32:42

2

删除通话.ToList()。它强制查询将整个结果拖到客户端。

通过直接在TR(不ToList())的结果中移除此,和只调用.Count之间()时,Count()变得查询本身的一部分,并且远程地执行,这将大大简化此:

public static int totalTracking(int id) 
{ 
    using (var ctx = new GPEntities()) 
    { 
     var tr = ctx.Tracking 
      .Where(c => c.clientID == Config.ClientID) 
      .Where(c => c.custID == id) 
      .Where(c => c.oOrderNum.HasValue); 

     // This can be added above, or left here - the end result is the same 
     return tr.Count(); 
    }   
} 
3

您可以非常简化的东西,只是使用Count Extension method

你试过:

public static int totalTracking(int id) 
{ 
    using (var ctx = new GPEntities()) 
    { 
     return ctx.Tracking.Count(
        c => c.clientID == Config.ClientID && 
         c.custID == id && 
         c.oOrderNum.HasValue); 
    }   
} 
+0

顺便说一句 - 错误的扩展方法链接 - 尝试http://msdn.microsoft.com/en-us/library/bb534807.aspx,而不是... – 2011-06-17 00:12:36

+0

@Reed Copsey thxs,如果微软将停止搞乱他们的文档,它会做回答StackOverflow问题非常容易:) – Nix 2011-06-17 00:13:52

+0

@Nik:没问题 - 你用的是IEnumerable,而不是IQueryable;) – 2011-06-17 00:18:53