具有2个多对多连接的实体框架查询

时间:2015-05-28 15:31:48

标签: c# sql-server entity-framework entity-framework-5

我正在开发一个首先使用EF代码且具有以下模型关系的项目:

Item (Id, Name, virtual List<Category>, virtual List<Tag>)  
Category (Id, Name, virtual List<Item>)  
Tag (Id, Name, virtual List<Item>)  

我正在运行搜索,我想获取项目名称= searchTerm的所有项目,类别ID包含在整数列表中,标签名称存在于标签列表中。

public IEnumerable<Item> Search(string searchTerm, IEnumerable<int> categoryIds, IEnumerable<string> tags)
{
    var query = (
        from i in context.Items
        from c in context.Categories
        from t in context.Tags
            where i.Name.Contains(searchTerm)
            && categoryIds.Contains(c.Id)
            && tags.Contains(t.Name)
        select i);

    return query.ToList();
}

在SQL中,查询将如下所示:

SELECT I.* FROM Items I
INNER JOIN ItemItemCategories IIC ON IIC.Item_Id = I.Id
INNER JOIN ItemCategories C ON C.Id = IIC.ItemCategory_Id
INNER JOIN ItemItemTags IIT ON IIT.Item_Id = I.Id
INNER JOIN ItemTags T On T.Id = IIT.ItemTag_Id
WHERE I.Question like '%sample%' -- searchTerm
AND C.Id in (1,2) -- categoryIds
AND (T.Text like '%Difficult%' OR T.Text like '%Technical%') -- tags

我的问题是如何构建我的代码以返回上面的查询。根据我的知识,这是执行查询的最有效方式。目前,正在从代码运行以下查询:

SELECT 
    [Filter1].[Id1] AS [Id], 
    [Filter1].[Name] AS [Name]
    FROM   (
    SELECT 
        [Extent1].[Id] AS [Id1], 
        [Extent1].[Name] AS [Name] 
        FROM  [dbo].[Items] AS [Extent1]
        CROSS JOIN [dbo].[Categories] AS [Extent2]
        WHERE [Extent2].[Id] IN (1, 2) ) AS [Filter1]
        CROSS JOIN [dbo].[Tags] AS [Extent3]
    WHERE ([Filter1].[Name] LIKE @p__linq__0 ESCAPE N'~') AND ([Extent3].[Name] IN (N'Difficult', N'Technical')) AND ([Extent3].[Name] IS NOT NULL)

1 个答案:

答案 0 :(得分:1)

试试这个:

var query = ( from i in context.Items
              from c in i.Categories
              from t in i.Tags
              where i.Name.Contains(searchTerm) 
              && categoryIds.Contains(c.Id)
              && tags.Contains(t.Name)
              select i).ToList();

您不必搜索所有类别和标签元素,只需搜索与您相关的人Item

关于您想要的查询,恕我直言,我不认为在Linq to Entities中有更高效的查询来获得您期望我上面提出的查询的结果。查看生成的sql代码:

   SELECT 
        [Filter1].[Id] AS [Id], 
        [Filter1].[Name] AS [Name]
   FROM   (SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name]
            FROM  [dbo].[Items] AS [Extent1]
            INNER JOIN [dbo].[ItemCategories] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Item_Id]
            WHERE [Extent2].[Category_Id] IN (1, 2) ) AS [Filter1]
            INNER JOIN  (SELECT [Extent3].[Item_Id] AS [Item_Id]
            FROM  [dbo].[TagItems] AS [Extent3]
            INNER JOIN [dbo].[Tags] AS [Extent4] ON [Extent4].[Id] = [Extent3].[Tag_Id]
            WHERE ([Extent4].[Name] IN (N'Difficult', N'Technical')) AND ([Extent4].[Name] IS NOT NULL) ) AS [Filter2] ON [Filter1].[Id] = [Filter2].[Item_Id]
   WHERE [Filter1].[Name] LIKE @p__linq__0 ESCAPE N'~'

正如您所看到的,它与您期望的查询非常相似。