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))
相當直觀地代表所有父母共有的孩子。

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
})

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 重新計算一次。

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();

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
};
});
- 5 回答
- 0 關注
- 136 瀏覽
添加回答
舉報