簡體   English   中英

EF Core如何選擇具有多對多關系的實體

[英]EF Core how select entity with many-to-many relationship

我是這樣的表結構

  1. 用戶
  2. user_profiles
  3. 型材

描述:

user有許多用戶配置文件,user_profile表連接用戶和配置文件表。(用戶和配置文件表之間存在多對多的關系)

用戶>一個一對多> user_profiles>一個對一>型材

user> many user_profiles>一個配置文件

問題:

如何使用linq選擇具有配置文件的用戶。

樣品:

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

找到了答案

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

如果你有完整的實體框架,那么多對多的設計類似於:

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,請使用(組)加入

我從一些人了解到,當您使用EF-core時,您無法使用virtual ICollections 在這種情況下,您必須自己執行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(),
        });

小心:沒有任何配置文件,您將無法獲得用戶!
這是一個內部聯接。

如果您還希望用戶沒有配置文件,請使用Stackoverflow中所述Left-Outer-GroupJoin向下滾動以獲得排名最高的答案,這比選擇的答案更好

除了你自己對lambda的回答和ThenInclude的使用,這是我對n到n關系的簡單查詢的首選版本,你還可以使用字符串來指定包含。

您只需要編寫用點分隔的屬性的“路徑” . 像這樣 :

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

它適用於1對1,1對多,多對多關系相同。

當你有深層的實體包含時(但你丟失了編譯時檢查)它很有用

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM