【问题标题】:Entity Framework - How to improve query with many-to-many relationship实体框架 - 如何改进具有多对多关系的查询
【发布时间】:2013-12-24 05:36:16
【问题描述】:

我想选择所有餐厅,并为每个餐厅加载附加类别的列表。

Restaurant 和 Category 之间存在多对多关系:

public class Restaurant
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual List<Category> Categories { get; set; }
}

public class Category
{
    public int Id { get; set; }
    public string Value { get; set; }
}

在我当前的实现中,我选择包含所有餐厅和类别的原始数据,并在客户端处理它们:按餐厅分组并选择类别。在这种情况下,生成的 SQL 看起来非常简单且执行速度很快:

var plainData = (
    from restaurant in RestaurantsRepository.GetAll()
    from category in restaurant.Categories
    select new
        {
            Id = restaurant.Id,
            Name = restaurant.Name,
            Category = category.Value
        }).ToList();

var restaurants = (
    from restaurant in plainData
    group restaurant by new
        {
            restaurant.Id,
            restaurant.Name
        }
    into grp
    select new RestaurantModel
        {
            Id = grp.Key.Id,
            Name = grp.Key.Name,
            Categories = grp.Select(c => c.Category).ToList()
        });

另一个变体是使用实体框架以及餐厅和类别之间的关系。在这种情况下,生成的 SQL 非常复杂,执行速度要慢四倍:

var restaurants =(
    from restaurant in RestaurantsRepository.GetAll()
    select new RestaurantModel
        {
            Id = restaurant.Id,
            Name = restaurant.Name,
            Categories = restaurant.Categories
        }).ToList();

问题是:有没有更有效的方法(然后是 1 或 2)来选择我的数据?

【问题讨论】:

    标签: c# performance linq entity-framework query-optimization


    【解决方案1】:

    您的收藏是virtual,因此,我想您正在使用延迟加载。
    第二个变体执行 N + 1 个查询,其中 N 是从 RestaurantsRepository.GetAll() 返回的项目计数:一个查询获取所有餐厅,N 个查询获取特定餐厅的所有类别。

    尝试使用预先加载的集合:

    RestaurantsRepository
        .GetAll()
        .Include(r => r.Categories)
    

    这应该使用JOIN 对数据库执行单个查询,如下所示(实际 SQL 会有所不同):

    SELECT
        *
    FROM
        [Restaurants] JOIN [Categories] ON [Restaurants].Id = [Categories].[RestaurantId]
    

    另外,考虑延迟加载 - 如果您将查询结果映射到其他类型(示例中为 RestaurantModel),您真的需要它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-13
      • 2016-12-15
      • 1970-01-01
      • 1970-01-01
      • 2018-06-26
      • 1970-01-01
      相关资源
      最近更新 更多