简体   繁体   English

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

[英]Entity Framework query with 2 many-to-many joins

I'm working on a project which is using EF Code first and has the following model relationships: 我正在研究一个首先使用EF代码并且具有以下模型关系的项目:

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

I'm running a search where I would like to get all items where the item name = searchTerm, the category id is contained in a list of ints and where the tag name exists in a list of tags. 我正在运行一个搜索,我想获取所有项目,其中项目名称= searchTerm,类别ID包含在int列表中,并且标签名称存在于标签列表中。

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

In SQL the query would look like the following: 在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

My question is how can I form my code to return the query above. 我的问题是如何形成我的代码以返回上面的查询。 This is the most efficient way to perform the query from my knowledge. 据我所知,这是执行查询的最有效方法。 Currently the following query is being run from code: 当前,以下查询正在从代码运行:

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)

Try this: 尝试这个:

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

You do not have to search through all the categories and tags elements, only those who are related with you Item . 您没有通过所有的类别和标签元素,只有那些谁与你相关的搜索Item

About the query you want, IMHO I don't think there's a more efficient query in Linq to Entities to get the result you are expecting that the query I propose above. 关于您想要的查询,恕我直言,我认为Linq to Entities中没有更有效的查询来获得您期望的结果,即我上面提出的查询。 Look the sql code that is generated: 查看生成的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'~'

As you can see it is quite similar with the query that you expect. 如您所见,它与您期望的查询非常相似。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM