Системы управления базами данных оптимизированы для выбора данных. Одна из более медленных частей - это транспортировка выбранных данных в ваш процесс. Следовательно, разумно перевозить только те данные, которые вы действительно планируете использовать.
Если у вас есть отношение «один ко многим», например Schools
с их Students
, а School
10 имеет 1000 Students
, то каждый Student
из этого School
будет иметь внешний ключ SchoolId
со значением 10.
Итак, если вы выбираете «Школа [10] с ее учениками», вы уже знаете, что у каждой Student
школы [10] будет свойство SchoolId
со значением 10. Это значение (которое вы уже знаете) будет перевезено 1000 раз (1001, если вы также посчитаете первичный ключ школы). Какая трата вычислительной мощности!
Если вы запрашиваете данные с использованием структуры сущностей, всегда используйте Select
. Используйте Include
только если вы хотите обновить извлеченные данные (изменить, удалить)
Использование Select позволяет вам выбирать только те свойства, которые вам нужны, в нужном формате.
Вернуться к вашей проблеме
Увы, вы забыли дать нам свои уроки. Так что нам придется угадать это. Кажется, что User
имеет ноль или более Languages
, CreatedEvents
, Friends
, Hobbies
и т. Д. Некоторые из них будут отношением один-ко-многим, вероятно, большинство из них будет много отношение ко многим: пользователь знает ноль или более языков. На каждом языке говорят ноль или более пользователей.
Если вы следовали первым соглашениям кода структуры сущности , у вас, вероятно, есть классы, подобные:
class User
{
public int Id {get; set;}
public string Name {get; set;}
// every User has zero or more Hobbies (many-to-many)
public virtual ICollection<Hobby> Hobbies {get; set;}
// every Student has created zero or more events (one-to-many)
public virtual ICollection<CreatedEvent> CreatedEvents {get; set;}
...
}
class Hobby
{
public int Id {get; set;}
public string Name {get; set;}
...
// every Hobby is practised by zero or more Users (many-to-many)
public virtual ICollection<User> Users {get; set;}
}
class CreatedEvent
{
public int Id {get; set;}
public string Name {get; set;}
public DateTime Date {get; set;}
// every event is created by exactly one User (one-to-many, using foreign key)
public int UserId {get; set;}
public virtual User User {get; set;}
}
и т.д.
В каркасе сущностей столбцы ваших таблиц представлены не виртуальными свойствами. Виртуальные свойства представляют отношения между таблицами (один ко многим, многие ко многим, ...)
Следовательно, внешний ключ не является виртуальным. Элемент, на который указывает внешний ключ, является виртуальным. Если два класса имеют virtual ICollection<...>
, указывающие друг на друга, структура сущности знает, что существует отношение «многие ко многим»; если один из двух классов имеет virtual ICollection<...>
, а другой - virtual ...
, то структура сущностей знает, что вы намеревались создать отношение один ко многим.
Если вы создали свои классы правильно, особенно virtual ICollections
, запрос с использованием Select
довольно прост. Вы редко должны делать (групповое) присоединение больше. Поскольку вы используете виртуальные свойства, структура сущностей знает, что необходимо (групповое) соединение.
var queryUsers = dbContext.User.Where(...).Where(...) ...
.Select(user => new
{
// select only the user properties you really plan to use
Id = user.Id,
BirthDay = user.BirthDay,
// Select the data in the format that you want, for example:
FullName = user.FirstName + user.MiddleName + user.LastName,
// SubCollections:
Languages = user.Hobbies
.Where(hobby => ...) // only if you don't want all this user's hobbies
.Select(hobby => new
{
// again, select only the hobby properties that you plan to use
Id = hobby.Id,
...
// not needed, you already know the value:
// I know, it is probably a many-to-many, but let's suppose it is one-to-many
// UserId = hobby.UserId,
})
.ToList(),
...
});
Теперь ваша проблема в собственности Friends
, вы можете добавить ее в свой выбор, точно так же, как вы выбрали Hobbies
Friends = user.Friends
.Where(friend => ...) // only if you don't want all Friends
.Select(friend => new
{
// select the Friend properties you actually plan to use:
Id = friend.Id,
Name = friend.Name,
...
})
.ToList(),
// continue the select