亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

讓所有父母共有的孩子

讓所有父母共有的孩子

C#
人到中年有點甜 2022-11-22 16:16:53
我有以下使用 Entity Framework Core 的實體:public class Parent {  public Int32 ParentId { get; set; }  public virtual Collection<ParentChildren> ParentChildrens { get; set; }}public class ParentChildren {  public Int32 ParentId { get; set; }  public Int32 ChildrenId { get; set; }  public virtual Parent Parent { get; set; }  public virtual Children Children { get; set; }}public class Children {  public Int32 ChildrenId { get; set; }  public virtual Collection<ParentChildren> ParentChildrens { get; set; }  public virtual Collection<ChildrenLocalization> ChildrenLocalizations { get; set; }}public class ChildrenLocalization {  public Int32 ChildrenId { get; set; }  public String Language { get; set; }  public String Name { get; set; }  public virtual Children Children { get; set; }}鑒于IQueryable<Parent>我需要,使用 Linq to Entities lambda 表達式:獲取所有 Parents 共有的 Children;對于每個從withChildren獲取其名稱。ChildrenLocalizationLanguage="en"所以我嘗試了以下方法:var result = context.Parents  .SelectMany(y => y.ParentChildrens)  .GroupBy(y => y.ParentId)  .Where(y =>      context.Parents       .SelectMany(y => y.ParentChildrens)       .Select(z => z.ChildrenId)       .Distinct()       .All(z => y.Any(w => w.ChildrenId == z)))  .SelectMany(y => y)  .Select(y => new {    Id = y.ChildrenId,    Name = y.Children.ChildrenLocalizations.Where(z => z.Language == "en").Select(z => z.Name).FirstOrDefault()  })  .GroupBy(x => x.Id)  .Select(x => x.FirstOrDefault())  .ToList();此查詢給出了預期的結果,但它似乎太復雜了。我無法改進它,例如,我需要添加最后一個 GroupBy 才能使其工作。如何使我的查詢更簡單?
查看完整描述

5 回答

?
交互式愛情

TA貢獻1712條經驗 獲得超3個贊

由于您擁有多對多關系,因此最好將查詢基于(開始)結果實體 ( Children),從而避免需要GroupBy/Distinct如果您從另一端 ( Parent) 開始它。


所以給出


IQueryable<Parent> parents

并假設您有權訪問上下文,則可以按如下方式編寫查詢:


var query = context.Set<Children>()

    .Where(c => parents.All(p => p.ParentChildrens.Select(pc => pc.ChildrenId).Contains(c.ChildrenId)))

    .Select(c => new

    {

        Id = c.ChildrenId,

        Name = c.ChildrenLocalizations.Where(cl => cl.Language == "en").Select(cl => cl.Name).FirstOrDefault()

    });

這很好地轉換為單個 SQL。


您從unique Children開始。對于要求 (2),您只需使用導航屬性。要求 (1) 更復雜(all總是比any更難實現),但我認為標準


parents.All(p => p.ParentChildrens.Select(pc => pc.ChildrenId).Contains(c.ChildrenId))

相當直觀地代表所有父母共有的孩子。


查看完整回答
反對 回復 2022-11-22
?
BIG陽

TA貢獻1859條經驗 獲得超6個贊

鑒于IQueryable<Parent> parents


parents

.SelectMany(p => p.ParentChildrens)

.Select(pc => pc.Children)

.Where(c => c.ParentChildrens

    .Select(pc => pc.ParentId)

    .OrderBy(i => i)

    .SequenceEqual(parents.Select(p => p.ParentId).OrderBy(i => i)))

.Select(c => new

{

    Id = c.ChildrenId,

    c.ChildrenLocalizations.FirstOrDefault(cl => cl.Language == "en").Name

})


查看完整回答
反對 回復 2022-11-22
?
白板的微信

TA貢獻1883條經驗 獲得超3個贊

假設你有 3 個父母,ID 為 10、11、12 假設你有 3 個孩子,ID 為 20、21、22


父子表:


ChildId | ParentId

  20         10

  20         11

  20         12

  21         10

  21         11

  22         10

  22         12

所以孩子 20 有父母 10/11/12;孩子 21 有父母 10/11;孩子 22 有父母 10/12。


“獲得所有父母共有的孩子”;如果這意味著:獲取在其父母集合中具有每個可用父母的孩子,那么很容易看出您只想要 20 個孩子,并且您只想要這個孩子一次


因為所有的父子關系都是唯一的,我們知道如果有 X 個父母,我們想要的孩子正好有 X 個父母。


你不想要這些孩子的所有屬性,你只想“從 ChildrenLocalization 中獲取它的名字 Language="en ",是否總是有零個或一個這樣的名字?如果有更多我們應該取哪個?任何名字,或所有的名字?


因為我們需要將自己限制為 ParentCount 等于父母數量的所有孩子,所以我們還需要計算每個孩子的父母數量


var childrenWithParentCount = dbContext.Children.Select(child => new

{

    // "get its name from ChildrenLocalization with Language="en"

    LocalizationName = child.ChildrenLocalizations

                            .Where(localization => localization.Language == "en")

                            .Select(localization => localizaition.Name)

                            .FirstOrDefault();


    // or if you want all names:

    LocalizationNames = child.ChildrenLocalizations

                             .Where(localization => localization.Language == "en")

                             .Select(localization => localizaition.Name)

                            .ToList;


    ParentCount = child.ParentChildren

                       .Select(parentChild => parentChild.ParentId)

                       .Count();

});

現在我們不想要所有這些孩子,我們只想要那些 ParentCount 等于 Parents 數量的孩子


var childrenWithAllParents = childrenWithParentCount

    .Where(child => !child.ParentCount == dbContext.Parents.Count());

你注意到了嗎,我只創建了 IQueryable 對象,我還沒有執行任何查詢。要執行查詢:


var result = childrenWithAllParents.ToList();

有些人喜歡用一個大的 LINQ 語句來打動別人;好吧,它是:


var result = dbContext.Children.Select(child => new

{

    LocalizationName = child.ChildrenLocalizations

          .Where(localization => localization.Language == "en")

          .Select(localization => localizaition.Name)

          .FirstOrDefault();


    ParentCount = child.ParentChildren

                       .Select(parentChild => parentChild.ParentId)

                       .Count();

})

.Where(child => !child.ParentCount == dbContext.Parents.Count())

.ToList();

幸運的是,您的數據庫管理系統足夠聰明,可以記住 Parents 的數量,而不是為每個 Child 重新計算一次。


查看完整回答
反對 回復 2022-11-22
?
紅顏莎娜

TA貢獻1842條經驗 獲得超13個贊

如果我理解正確,這可能會起作用。這將是一個單一的查詢。


    var result =

            (from parent in context.Parents

            from pToC in parent.ParentChildrens

            where pToC.Children.ParentChildrens.Select(pc => pc.ParentId).Distinct().Count() == context.Parents.Count()

            from childLocation in pToC.Children.ChildrenLocalizations

            where childLocation.Language == "en"

            select new { pToC.Children.ChildrenId, childLocation.Name }).Distinct();



查看完整回答
反對 回復 2022-11-22
?
慕容3067478

TA貢獻1773條經驗 獲得超3個贊

您需要將呼叫從您的分組中分離出來。


  List<Parent> result = context.Parents

                .Include(i => i.ParentChildrens)

                .ThenInclude(i => i.Children)

                .ThenInclude(i => i.ChildrenLocalizations)

                .ToList();


            var finalResult = result.SelectMany(c => c.ParentChildrens, (o, j) =>

            {

                return new

                {

                    Id = j.ChildrenId,

                    Parent = o.ParentId,

                    Name = j.Children.ChildrenLocalizations.First(c => c.Language == "en").Name

                };

            });


查看完整回答
反對 回復 2022-11-22
  • 5 回答
  • 0 關注
  • 136 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號