使用 linq/Entity Framework 查询多对多关系。代码优先

Posted

技术标签:

【中文标题】使用 linq/Entity Framework 查询多对多关系。代码优先【英文标题】:Query a many-to-many relationship with linq/Entity Framework. CodeFirst 【发布时间】:2015-08-08 14:35:57 【问题描述】:

如何使用实体框架代码优先和 linq 查询多对多关系?问题是 EF 自动创建关系表。所以,我的上下文中没有它。

这是关系模型:

我需要一个特定 Category_Id 的文章列表,基本上复制类似的内容:

select a.Id, a.Title,a.ShortDescription                       
from Articles a
join CategoryArticles ca on ca.Article_Id=a.Id
where ca.Category_Id  = @parameter

但是我的 dbcontext 只有:

public DbSet<Article> Articles  get; set; 
public DbSet<Category> Categories  get; set; .

感谢您的帮助。

【问题讨论】:

【参考方案1】:

你可以这样做:

var cat_id=1; // Change this variable for your real cat_id

var query= from article in db.Articles
           where article.Categories.Any(c=>c.Category_ID==cat_id)
           select article;

这样你会得到满足你想要的条件的文章。这是该查询生成的 sql 代码:

    SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Title] AS [Title]
    FROM [dbo].[Articles] AS [Extent1]
    WHERE  EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[ArticleCategories] AS [Extent2]
        WHERE ([Extent1].[Id] = [Extent2].[Article_Id]) AND ([Extent2].[Category_Id] = @p__linq__0))

更新

另一种选择可能是使用SelectMany 扩展方法(正如@Khaled 指出的那样)从Categories 而不是Articles 开始查询:

var query= db.Categories.Where(c=>c.Category_ID==cat_id).SelectMany(c=>Articles);

这将生成一个内部连接,而不是 EXIST,它是 Any 扩展方法的产物。

【讨论】:

这是不正确的,EF 不够聪明,无法使用联接。它将改为创建一个 EXISTS 语句。性能可能是这里的一个问题。 @Talon,现在我测试了该查询,确实 EF 6.x Linq 提供程序正在生成 Exists 而不是 join。感谢您的反馈。同意您对性能的看法,但如果您在模型中省略连接表,这是唯一的方法。 @octavioccl 同意,如果没有那个连接表,我还没有找到解决方法。我认为这些隐式连接表是个坏消息,但需要做大量工作才能以最少的回报移除它们。 对于使用 INNER JOIN 的更快查询,请参阅 Khaled 的以下回答:***.com/a/41244639/193634【参考方案2】:

怎么样

db.Categories.Where(c => c.Id == categoryId).SelectMany(c => c.Articles)?

这应该可以正常工作(生成正确的连接 sql 语句。)

【讨论】:

'a' 来自哪里?你能澄清一下你的意思吗? 应该是 c =&gt; c.Articles 。这将加入从 Where 查询中选择的类别的每篇文章列表。 太好了,这是正确的解决方案。 EF 生成了 INNER JOIN,而不是 WHERE EXISTS。使用 EXISTS 非常慢。【参考方案3】:

我刚刚遇到了这个问题,我想我会发布我找到的解决方案,供任何偶然发现此页面的人使用。这会产生一个INNER JOIN

var category_id = 24;

var query = (from article in Articles
             from category in article.Categories.Where(x => x.Category_ID == category_id)
             select article);

【讨论】:

【参考方案4】:

如果您只想要包含所有关系的整个表,可以尝试这样的操作:

List<CategoryArticle> rec = context.Category.SelectMany(a => a.Articles.Select(c => new CategoryArticle  Category_Id = c.Id, Article_Id = a.Id )).ToList();

【讨论】:

【参考方案5】:

示例 linq 方法语法

int category_ID = 1;

var query = db.Articles
    .Where(a => a.Categories
    .Any(c => c.Category_ID == category_ID))
    .ToList();

【讨论】:

【参考方案6】:

添加和查询联结表:

  var articles = (from ca in _context.CategoryArticles
                  inner join a in _context.Articles on a.Id equals ca.Article_Id
                  inner join c in _context.Catgories on c.Id equals ca.Category_Id
                  where ca.Category_Id equals catId
                  select c).ToList();

【讨论】:

以上是关于使用 linq/Entity Framework 查询多对多关系。代码优先的主要内容,如果未能解决你的问题,请参考以下文章

iOS framework动态库的创建和使用

【重要】SDK开发中使用三方framework的方法

IOS多语言切换4-framework中的语言切换和资源使用

android如何使用framework层的方法

iOS 使用 Cmake 生成 framework 库

使用 ChatKit.framework 时出错