【问题标题】:Efficient count (using GROUP BY) for collection in Entity Framework实体框架中收集的有效计数(使用 GROUP BY)
【发布时间】:2011-08-09 04:41:20
【问题描述】:

我将 Entity Framework 4.1 与 ASP.NET MVC 3 结合使用。我有两个具有一对多关系的表,比如说 ShopShopVisit,我想显示 Shops 列表以及 Visits 的计数。作为 SQL 查询很简单,但我如何让 Entity Framework 有效地做到这一点?

这行得通:

_db.Shops.Include("Visits").ToList();


@foreach (var shop in ViewBag.Shops)
{
    Visit count: @shop.Visits.Count
}

但是,查看 SQL Profiler,它似乎正在使用 LEFT OUTER JOIN 加载所有访问,这不是我想要的。我只想要计数。当然,我也不希望对每个 Shop 都进行子查询。我该怎么做才能让它执行COUNT(*) ... GROUP BY 查询?

即使我这样选择:

_db.Shops.Include("Visits").Select(s => ShopStats { Shop = s, Vists = s.Vists.Count}).ToList();

它仍然坚持执行 LEFT OUTER JOIN,它会加载所有访问。

【问题讨论】:

    标签: linq-to-entities group-by entity-framework-4.1


    【解决方案1】:

    在这种情况下,您需要创建自定义类型并使用投影:

    var data = from s in _db.Shops
               select new SomeCustomType 
                   {
                       Shop = s,
                       Count = s.Visits.Count()
                   };
    

    您也可以将SomeCustomType 展平,这样它将包含Shop 的所有属性,而不是商店本身。它可能会在查询内部执行左外连接,但不会加载对应用程序的访问。

    包含或延迟加载工作如您所述 - 计数将在内存中计算,因此必须加载所有访问。

    编辑:

    还有另一种解决方案,称为超延迟加载。它不支持开箱即用,但 you can extend EF to support it。在超延迟加载的情况下,您不会加载Visits,但Count 将触发对数据库的查询以获取访问次数。

    【讨论】:

    • 这就是我的意思 - 即使我使用自定义类型,无论是使用 Vists.Count 还是 Vists.Count(),它仍然会执行 LEFT OUTER JOIN。有没有办法让它做一个数据库 COUNT(*)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 2017-06-14
    • 2012-09-10
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    相关资源
    最近更新 更多