c# - LINQ 多对多在哪里

标签 c# linq entity-framework-core

如何编写 EF7(核心)/SQL 友好的多对多 LINQ 查询?

例如,我有很多说多种语言的 friend ,我想找到一组给定语言的所有 friend 。

class Friend
{
    Guid Id { get; set; }
    ICollection<FriendLanguage> Languages { get; set; }
}

class Language
{
    Guid { get; set; }
    ICollection<FriendLanguage> Friends { get; set; }
}

class FriendLanguage
{
    Friend { get; set; }
    Language { get; set; }
}

鉴于我有一组语言 ID IEnumerable<Guid> , 我想找回所有说这些语言的 friend 。

我试过了...

friends
    .Include(o => o.Languages).ThenInclude(o => o.Language)
    .SelectMany(o => o.Languages).Select(o => o.Language.Id)
    .Intersect(languages);

...但这只会返回一组减少的 Guids...不完全确定从这里到哪里去,或者即使我走在正确的道路上。

最佳答案

如果我没理解错的话,你想从列表中找到说所有语言的 friend 。

表达您的要求的最自然的 LINQ 查询是:

var friends = db.Friends
    .Include(o => o.Languages).ThenInclude(o => o.Language)
    .Where(o => languages.All(id => o.Languages.Any(fl => fl.Language.Id == id)));

不幸的是,它对 SQL 不友好。事实上,EF Core 目前无法将其转换为 SQL,而是会读取内存中的数据并在那里进行过滤。

所以你可以改用这个:

var friends = db.Friends
    .Include(o => o.Languages).ThenInclude(o => o.Language)
    .Where(o => o.Languages.Count(fl => languages.Contains(fl.Language.Id)) == languages.Count);

翻译成这样:

SELECT [o].[Id]
FROM [Friends] AS [o]
WHERE (
    SELECT COUNT(*)
    FROM [FriendLanguages] AS [fl]
    WHERE [fl].[LanguageId] IN ('6e64302f-24db-4717-a5fe-2cc61985ca3a', '2c216a63-1f6a-4fad-9105-d5f8ece3fa3c') AND ([o].[Id] = [fl].[FriendId])
) = @__languages_Count_1
ORDER BY [o].[Id]

如果您确实想要说列表中任何语言的 friend ,那么Where会更简单:

.Where(o => o.Languages.Any(fl => languages.Contains(fl.Language.Id)))

SQL 是:

SELECT [o].[Id]
FROM [Friends] AS [o]
WHERE EXISTS (
    SELECT 1
    FROM [FriendLanguages] AS [fl]
    WHERE [fl].[LanguageId] IN ('ed3f85a7-e122-45dd-b0af-2020052d55a7', '4819cb7d-ad43-41a0-a3a1-979b7abc6265') AND ([o].[Id] = [fl].[FriendId]))
ORDER BY [o].[Id]

关于c# - LINQ 多对多在哪里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40474349/

相关文章:

c# - IndexOf 谓词?

c# - 是否可以将小型查询合并为单个查询?

c# - 拥有类型的关系

asp.net-mvc - 使用 ID 的 Linq 查询返回结果缓慢(EF Core)

javascript - 无法打开ajaxToolkit :ModalPopupExtender with JavaScript

c# - 在 C# 中化简分数

c# - 对调用同一对象上的另一个公共(public)函数的函数进行单元测试的正确方法是什么?

c# - Windows 身份验证不适用于本地 IIS 7.5。错误 401.1

c# - 使用 (LINQ/Predicate) 将 DataTable 的所有列名放入字符串数组

linq - IQueryable 有什么大不了的?