Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在EF 4.1中,与LINQ的许多关系进行比较最有效的方法是什么?_C#_Asp.net_Asp.net Mvc_Entity Framework_Entity Framework 4 - Fatal编程技术网

C# 在EF 4.1中,与LINQ的许多关系进行比较最有效的方法是什么?

C# 在EF 4.1中,与LINQ的许多关系进行比较最有效的方法是什么?,c#,asp.net,asp.net-mvc,entity-framework,entity-framework-4,C#,Asp.net,Asp.net Mvc,Entity Framework,Entity Framework 4,在我的数据库中,我有以下表格: 人 职位 兴趣爱好 个人兴趣和后兴趣之间存在许多关系 我需要在EF 4.1中执行linq查询,以撤回包含至少一个兴趣标记的帖子,该兴趣标记至少与给定用户相关的一个兴趣标记相匹配 示例 一个人有以下利益: 汽车 运动 健康 我需要返回任何与汽车、运动或健身相关的帖子 就性能而言,编写此查询最有效的方法是什么 编辑 根据下面给出的答案,遇到错误 这可以很好地编译,但在运行时会引发错误: var matchingPosts = posts.Where(post

在我的数据库中,我有以下表格:

  • 职位
  • 兴趣爱好
个人兴趣和后兴趣之间存在许多关系

我需要在EF 4.1中执行linq查询,以撤回包含至少一个兴趣标记的帖子,该兴趣标记至少与给定用户相关的一个兴趣标记相匹配

示例

一个人有以下利益:

  • 汽车
  • 运动
  • 健康
我需要返回任何与汽车、运动或健身相关的帖子

就性能而言,编写此查询最有效的方法是什么

编辑

根据下面给出的答案,遇到错误

这可以很好地编译,但在运行时会引发错误:

var matchingPosts = posts.Where(post => post.Topics.Any(postTopic =>   person.Interests.Contains(postTopic)));
错误是:

Unable to create a constant value of type 'System.Collections.Generic.ICollection`1'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
有没有办法解决这个问题

编辑2

因此,我的课程结构如下:

public class Person
{
    public int PersonID {get; set;}
    public string FirstName {get; set;}
    public string LastName {get; set;}
    //other properties of types string, int, DateTime, etc.

    public ICollection<InterestTag> InterestTags {get; set;}      
}


public class Post
{
    public int PostID {get; set;}
    public string Title{get; set;}
    public string Content {get; set;}
    //other properties of types string, int, DateTime, etc.

    public ICollection<InterestTag> InterestTags {get; set;}


}

public class InterestTag
{
    public int InterestTagID { get; set; }
    public string InterestDescription { get; set; }
    public bool Active { get; set; }

    public ICollection<Person> Persons { get; set; }
    public ICollection<Post> Posts { get; set; }
}

编辑:我不得不编辑我的帖子,因为我忘记了帖子和主题之间的许多关系。现在应该可以了

我无法告诉您这是否是最有效的方法,但这将是一种使用LINQ查询的方法,因此应该是高效的:

var matchingPosts = posts.Where(post => post.Topics.Any(postTopic => person.Interests.Contains(postTopic)));
如果要使用并行执行,可以这样修改:

var matchingPosts = posts.AsParallel().Where(post => post.Topics.Any(postTopic => person.Interests.Contains(postTopic)));
在使用EF时,您需要以下查询:

var matchingPosts = from post in posts
    where post.Topics.Any(topic => person.Interests.Contains(topic))
    select post;

如果只从给定的
personId
(或
用户ID
)开始,则可以在一次往返中执行此查询,如下所示:

var posts = context.Posts
    .Intersect(context.People
        .Where(p => p.Id == givenPersonId)
        .SelectMany(p => p.InterestTags.SelectMany(t => t.Posts)))
    .ToList();
这将转换为SQL中的
INTERSECT
语句

您还可以通过两次往返来完成此操作:

var interestTagsOfPerson = context.People.Where(p => p.Id == givenPersonId)
    .Select(p => p.InterestTags.Select(t => t.Id))
    .SingleOrDefault();
// Result is an IEnumerable<int> which contains the Id of the tags of this person

var posts = context.Posts
    .Where(p => p.InterestTags.Any(t => interestTagsOfPerson.Contains(t.Id)))
    .ToList();
// Contains translates into an IN clause in SQL
第二种选择:

查询1(有关人员标签ID的列表):

查询2关于最终职位:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
FROM [dbo].[Posts] AS [Extent1]
WHERE  EXISTS (SELECT 
            1 AS [C1]
        FROM [dbo].[PostInterestTags] AS [Extent2]
WHERE ([Extent1].[Id] = [Extent2].[PostId]) AND ([Extent2].[TagId] IN (1,2,3))
)
在本例中,查询1返回(1,2,3),因此在查询2中的
In
子句中出现了(1,2,3)。

这是怎么回事:

context.Persons
       .Where(p => p.Name == "x")
       .SelectMany(p => p.Interests.SelectMany(i => i.Posts))
       .Distinct()
       .Take(10)
       .ToList();

Take()的存在是出于性能原因和分页。您不应该选择所有记录,因为首先,没有用户会读取数千条记录的列表,其次,结果集可能会在将来增长,查询将无法扩展。

不幸的是,在使用此查询(上面的第一个示例)时,我收到以下错误:无法创建“System.Collections.Generic.ICollection”“1”类型的常量值。在此上下文中仅支持基元类型('如Int32、String和Guid')。我不确定是什么原因导致此错误。你能提供你正在使用的类的结构吗?特别是类成员的类型会很有趣。我在上面添加了一些关于我的类和查询的更多信息。谢谢我试图根据我的情况调整你的答案,但我仍然得到了与我原来问题中指定的相同的错误。请参阅我的第二次编辑,以获得关于我尝试做什么的更详细解释。任何提示都将不胜感激。@stephen776:我测试的模型与您的模型完全一样(除了稍微不同的属性名称),而且它工作正常。在我的回答中,你试过两个版本中的哪一个?您是否真的遇到“无法创建常量值…”异常?在我的例子中,我看不出这是怎么发生的。您是否可以显示您正在测试的代码?我正在尝试的查询是:posts=posts.Where(x=>x.InterestTags.Any(tag=>person.InterestTags.Select(ut=>ut.InterestTagID.Contains(tag.InterestTagID));。。。其中,posts是Iqueryable,person是来自repository@stephen776:您是否在存储库中加载了带有
Include
person.interestattags
?你得到了什么例外?@stephen776:这是一个警告,因为你要求效率:当你用
Include
加载完整的
Person
对象及其
标记
集合时,你加载到内存中的内容超过了最终获得帖子所需的内容。为了避免这种情况,上面的第二个解决方案只加载标记ID,而第一个解决方案只需要
person.PersonID
。遵循这些方法,您不需要
包含
SELECT 
[Intersect1].[Id] AS [C1], 
[Intersect1].[Name] AS [C2], 
FROM  (SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name], 
    FROM [dbo].[Posts] AS [Extent1]
INTERSECT
    SELECT 
    [Join1].[Id] AS [Id], 
    [Join1].[Name] AS [Name], 
    FROM  [dbo].[PersonInterestTags] AS [Extent2]
        INNER JOIN (SELECT [Extent3].[TagId] AS [TagId],
                           [Extent4].[Id] AS [Id],
                           [Extent4].[Name] AS [Name]
                    FROM  [dbo].[PostInterestTags] AS [Extent3]
                    INNER JOIN [dbo].[Posts] AS [Extent4]
                        ON [Extent3].[PostId] = [Extent4].[Id] ) AS [Join1]
            ON [Extent2].[TagId] = [Join1].[TagId]
    WHERE 1 = [Extent2].[PersonId]) AS [Intersect1]
SELECT 
[Project1].[Id] AS [Id], 
[Project1].[C1] AS [C1], 
[Project1].[TagId] AS [TagId]
FROM ( SELECT 
    [Limit1].[Id] AS [Id], 
    [Extent2].[TagId] AS [TagId], 
    CASE WHEN ([Extent2].[PersonId] IS NULL)
                 THEN CAST(NULL AS int)
                 ELSE 1
             END AS [C1]
    FROM   (SELECT TOP (2) [Extent1].[Id] AS [Id]
        FROM [dbo].[People] AS [Extent1]
        WHERE 1 = [Extent1].[Id] ) AS [Limit1]
    LEFT OUTER JOIN [dbo].[PersonInterestTags] AS [Extent2]
            ON [Limit1].[Id] = [Extent2].[PersonId]
)  AS [Project1]
ORDER BY [Project1].[Id] ASC, [Project1].[C1] ASC
SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
FROM [dbo].[Posts] AS [Extent1]
WHERE  EXISTS (SELECT 
            1 AS [C1]
        FROM [dbo].[PostInterestTags] AS [Extent2]
WHERE ([Extent1].[Id] = [Extent2].[PostId]) AND ([Extent2].[TagId] IN (1,2,3))
)
context.Persons
       .Where(p => p.Name == "x")
       .SelectMany(p => p.Interests.SelectMany(i => i.Posts))
       .Distinct()
       .Take(10)
       .ToList();