[英]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
: 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; }
}
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.