Как я могу получить значение из .Include (), используя .ThenInclude () c - PullRequest
0 голосов
/ 02 мая 2019

У меня есть фильтр некоторых пользователей в моем проекте, и я хочу показать здесь друзей каждого пользователя.UserFrom - кто посылает запрос на дружбу, UserTo - кто его принимает.Поэтому мне нужно знать идентификатор в приведенном ниже коде, чтобы выбрать противоположное, потому что это будет его друг.

var users = await _context.User
            .Where(u => userFilter.Gender != null ?
                u.Gender == userFilter.Gender : true)
            .Where(u => (userFilter.Languages != null &&
                         userFilter.Languages.Count() != 0) ?
                userFilter.Languages.Any(fl => u.Languages.Any(
                    ul => ul.LanguageCode == fl &&
                        LevelInRange(ul, userFilter.MinLevel))) : true)
            .Where(u => (userFilter.MaxDistance != null) ?
                LocationHelper.GetDistanceBetween((double)u.Longitude, (double)u.Latitude,
                longtitude, latitude) <= userFilter.MaxDistance : true)
            .Where(u => (userFilter.MaxAge != null) ?
                GetAge(u.Birthdate) <= userFilter.MaxAge : true)
            .Where(u => (userFilter.MinAge != null) ?
                GetAge(u.Birthdate) >= userFilter.MinAge : true)
            .Include(u => u.Languages)
            .ThenInclude(ul => ul.Language)
            .Include(u => u.CreatedEvents)
            .Include(u => u.Friends)
            .ThenInclude(f => f.UserTo) //The problem is here. How can I get u.Id there
            .Include(u => u.Credentials)
            .Include(u => u.Hobbies)
                .ThenInclude(h => h.Hobby)
            .ToListAsync();

Ответы [ 2 ]

1 голос
/ 03 мая 2019

Системы управления базами данных оптимизированы для выбора данных. Одна из более медленных частей - это транспортировка выбранных данных в ваш процесс. Следовательно, разумно перевозить только те данные, которые вы действительно планируете использовать.

Если у вас есть отношение «один ко многим», например 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
0 голосов
/ 02 мая 2019

IIRC, Вы можете выбрать () для детей с выражениями Linq, как для детей, использующих .Include ().

return _context.User
 .Include(a => a.Friends.Select(c => c.UserTo));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...