简体   繁体   English

实体框架-如何通过多对多关系改善查询

[英]Entity Framework - How to improve query with many-to-many relationship

I want select the all restaurants, and for the each restaurant load the list of the attached categories. 我要选择所有餐厅,并为每个餐厅加载附加类别的列表。

There is a many-to-many relationship between the Restaurant and Category : RestaurantCategory之间存在多对多关系:

在此处输入图片说明

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; }
}

In my current implementation I'm selecting a raw data with all restaurants and categories, and process them on the client side: group by restaurant and select categories. 在当前的实现中,我将选择包含所有餐厅和类别的原始数据,并在客户端进行处理:按餐厅分组并选择类别。 In this case, the generated SQL looks very simple and executed fast: 在这种情况下,生成的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()
        });

The another variant is to use Entity Framework and the relation between restaurants and categories. 另一个变体是使用实体框架以及餐厅和类别之间的关系。 In this case, the generated SQL is very complicated and executed four times slower: 在这种情况下,生成的SQL非常复杂,执行速度要慢四倍:

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

The question is: There is there a more efficient way (then 1 or 2) to select my data? 问题是:还有一种更有效的方式(然后1或2)来选择我的数据吗?

Your collection is virtual , thus, I suppose, you're using lazy loading. 您的集合是virtual ,因此,我想,您正在使用延迟加载。
The second variant executes N + 1 queries, where N is a count of items, returned from RestaurantsRepository.GetAll() : one query to get all restaurants, and N queries to get all categories for the particular restaurant. 第二个变体执行N + 1个查询,其中N是从RestaurantsRepository.GetAll()返回的项数:一个查询用于获取所有餐厅,而N个查询用于获取特定餐厅的所有类别。

Try to use eager loading of collection: 尝试使用集合的急切加载:

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

This should execute single query with JOIN against database, like this (real SQL will differ): 这应该使用JOIN对数据库执行单个查询,如下所示(实际SQL会有所不同):

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

Also, think about lazy loading - do you really need it, if you're mapping query result into another types ( RestaurantModel in your sample). 另外,考虑一下延迟加载-如果要将查询结果映射到其他类型(示例中的RestaurantModel ),是否真的需要它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM