使用多对多关系进行查询的正确方法

时间:2012-05-21 10:36:56

标签: entity-framework entity-framework-4 ef-code-first

我创建了三个表 - Podcast,Category和CategoryLink。 CategoryLink表只包含两列--PodcastId和CategoryId。 我已经描述了这些表之间的多对多关系,如article所述。 一切正常,但我不知道如何正确查询。 现在我通过以下方式做到这一点:

var ps = db.Podcasts.Where(p => p.Status.SysStatus > 0);
if (category_id.HasValue)
    ps = ps.Where(p => p.Categories.Where(c => c.Id == category_id.Value).FirstOrDefault() != null);

它有效,但我认为这有点肮脏: - )

它给我以下SQL查询(我删除了多余的列和字符串):

    SELECT 
[Project2].[Id] AS [Id]
FROM ( SELECT 
    [Extent1].[Id] AS [Id], 
    (SELECT TOP (1) 
        [Extent3].[CategoryId] AS [CategoryId]
        FROM [dbo].[CategoryLink] AS [Extent3]
        WHERE ([Extent1].[Id] = [Extent3].[PodcastId]) AND ([Extent3].[CategoryId] = 1)) AS [C1]
    FROM  [dbo].[Podcast] AS [Extent1]
    INNER JOIN [dbo].[PodcastStatus] AS [Extent2] ON [Extent1].[StatusId] = [Extent2].[Id]
    WHERE [Extent2].[SysStatus] > 0
)  AS [Project2]
WHERE [Project2].[C1] IS NOT NULL

问题是如何进行查询以便我可以在没有子查询的情况下获得“正常”inner join

感谢。

1 个答案:

答案 0 :(得分:0)

我不确定你要完成什么。在对象映射中,多对多与多对一没有太大区别,除了您可以从双方访问关系:

using System.Data.Entity; // For .Include Extension

// Eager-load Categories
var podcasts = db.Prodcasts.Include(x => x.Categories);
foreach (var p in podcats)
{
    foreach (var c in p.Categories)
    {
    }
}

var categories = db.Categories.Include(x => x.Podcasts);
foreach (var c in categories)
{
    foreach (var p in c.Podcasts)
    {
    }
 }

根据您尝试完成的任务,您可能还希望执行以下操作:

from c in Customers
join p in Purchases on c.ID equals p.CustomerID           // first join
join pi in PurchaseItems on p.ID equals pi.PurchaseID     // second join
select new
{
c.Name, p.Description, pi.Detail
}

如果您是LINQ的新手,我建议您查看LinqPad。它包含了很多可以让您了解其工作原理的示例。

<强>更新

你能详细说明你真正想要的东西吗?

我的第二个例子中的select也可以在没有PurchaseItems类的情况下完成:

var q = (from p in db.Prodcasts
        from c in p.Categories // note that it is using "p" instead of db.Categories
        select new 
        {
            Podcast = p.Name,
            CategoryName = c.Name
        }).ToList();