EF Core как выбрать сущность со многими ко многим - PullRequest
0 голосов
/ 01 октября 2018

Я имею такую ​​структуру таблицы

  1. пользователи
  2. user_profiles
  3. профили

описание:

У пользователя много профилей пользователей, таблица user_profile объединяет таблицы пользователей и профилей (между пользователем и таблицей профилей существует много-много взаимосвязей)

user> one-to-many> user_profiles> one-to-one> анкеты

user> many user_profiles> one profile

Проблема:

Как выбрать пользователя с профилем с помощью linq.

sample:

var user=cbContext.user.include("user_profiles").include("profiles").Where(predicate).FirstOrDefault();

Ответы [ 3 ]

0 голосов
/ 01 октября 2018

В дополнение к вашему собственному ответу с лямбдами и использованию ThenInclude, который является моей предпочтительной версией для простых запросов с отношениями n к n, вы также можете использовать строки, чтобы указать свои включения.

Вам просто нужно написать «путь» свойств, разделенных точками . следующим образом:

dbContext.Users
  .Include("UserProfiles.Profile")
  .Where(predicate)
  .FirstOrDefault();

Это работает для отношений 1 к 1, 1 ко многим и многих ко многимто же самое.

Это полезно, когда у вас есть глубокие включения сущностей (но вы теряете проверку во время компиляции)

0 голосов
/ 01 октября 2018

Если у вас есть полная структура сущностей, то конструкция «многие ко многим» разработана следующим образом:

class User
{
     public int Id {get; set;}

     // every User has zero or more Profiles (many-to-many)
     public virtual ICollection<Profile> Profiles {get; set;}

     ...
}
class Profile
{
     public int Id {get; set;}

     // every Profile belongs to zero or more Users (many-to-many)
     public virtual ICollection<User> Userss {get; set;}

     ...
}

Если ваши классы разработаны так, и вы хотите, чтобы «пользователи, которые ... сих профили "вы можете использовать коллекции и выбрать свойства, которые вы планируете использовать:

using (var dbContext = new MyDbContext(...))
{
    var requestedUsers = dbContext.Users
        .Where(user => ...)                      // only if you don't want all Users
        .Select(user => new
        {    // Select only the properties you plan to use:
             Id = user.Id,
             Name = user.Name,
             ...
             Profiles = user.Profiles
                 .Where(profile => ...)         // only if you don't want all profiles
                 .Select(profile => new
                 {
                      Name = profile.Name,
                      ...
                 })
                 .ToList(),
        })

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

Include выберет все свойства включенного объекта, включая первичные и внешние ключи.Include a Collection выберет полную коллекцию, даже если вы планируете использовать только несколько.

Совет: используйте Include, только если вы планируете изменить извлеченные данные.Использование Select быстрее.Select только те свойства, которые вы на самом деле планируете использовать

Использовать (группа) Присоединяйтесь, если вы не можете использовать ICollection

Из некоторых я понял, чтовы не можете использовать virtual ICollections при использовании EF-ядра.В этом случае вам придется выполнить GroupJoin самостоятельно

dbContext.Users
    .Where(user => ...)
    .GroupJoin(dbContext.UserProfiles,         // GroupJoin the users with the UserProfiles
        user => user.Id                        // from every user take the Id
        userProfile => userProfile.UserId,     // from every userProfile take the UserId
        (user, userProfiles) =>  new           // when thay match,
        {                                      // take the user and its matching UserProfiles
            UserId = user.Id,                  // again: select only properties you plan to use
            UserName = user.Name,
            ...

            // for the Profiles, do a new Join with the Profiles
            Profiles = userProfiles.Join(dbContext.Profiles, // join with Profiles
               userProfile => userProfile => profileId       // from the userProfile take profileId
               profile => profile.Id,                        // from the Profile take the Id
               (userProfile, profile) => new                 // when they match, make an object
               {   // again: use only properties you plan to use
                   ProfileId = profile.Id,
                   ProfileName = profile.Name,
                   ...
               })
               .ToList(),
        });

Осторожно: вы не получите пользователей без каких-либо профилей!
Это внутреннее объединение.

Если вы также хотите, чтобы пользователи без профилей, используйте Left-Outer-GroupJoin, как описано здесь для Stackoverflow Прокрутите вниз, чтобы получить ответ с наивысшим рейтингом, который намного лучше, чем выбранный ответ

0 голосов
/ 01 октября 2018

Нашел ответ

dbContext.Users
  .Include(user => user.UserProfiles)
  .ThenInclude(userProfiles => userProfiles.Profile) 
  .Where(predicate)
  .FirstOrDefault();
...