C# 在实体框架中查询常见联系人(自多对多关系)

C# 在实体框架中查询常见联系人(自多对多关系),c#,entity-framework,linq-to-entities,C#,Entity Framework,Linq To Entities,我有一个经典场景,其中有一个用户表和一个联系人表,其中只包含UserId和ContactId列(因此它是一个自多对多关系shsip)。我想要的是一个查询,它为我提供一个userid列表,其中包含与指定用户的常见联系人的数量。在纯旧SQL中,我有以下查询(用户和用户本身的联系人被过滤掉,以获得类似facebook的朋友建议): 这个简单的查询非常有效,但我不知道如何在LINQ中编写相同的查询到实体,因为在实体框架模型中,我有一个用户实体,该实体具有Contact导航属性,但连接表不直接存在 非常感

我有一个经典场景,其中有一个用户表和一个联系人表,其中只包含UserId和ContactId列(因此它是一个自多对多关系shsip)。我想要的是一个查询,它为我提供一个userid列表,其中包含与指定用户的常见联系人的数量。在纯旧SQL中,我有以下查询(用户和用户本身的联系人被过滤掉,以获得类似facebook的朋友建议):

这个简单的查询非常有效,但我不知道如何在LINQ中编写相同的查询到实体,因为在实体框架模型中,我有一个用户实体,该实体具有Contact导航属性,但连接表不直接存在


非常感谢您的帮助…

没有时间尝试运行它,但类似的操作应该可以运行

public class Test
    {
        //simulate an IQueryable
        private readonly IQueryable<Person> _people = new List<Person>().AsQueryable();

        public void FindContactMatchCount(Guid personId)
        {
            //we'll need the list of id's of the users contacts for comparison, we don't need to resolve this yet though so 
            //we'll leave it as an IQueryable and not turn it into a collection
            IQueryable<Guid> idsOfContacts = _people.Where(x => x.Id == personId).SelectMany(x => x.Contacts.Select(v => v.Id));

            //find all the people who have a contact id that matches the selected users list of contact id's
            //then project the results, this anonymous projection has two properties, the person and the  contact count
            var usersWithMatches = _people
                .Where(x => idsOfContacts.Contains(x.Id))
                .Select(z => new
                    {
                        Person = z, //this is the person record from the database, we'll need to extract display information
                        SharedContactCount = z.Contacts.Count(v => idsOfContacts.Contains(v.Id)) //
                    }).OrderBy(z => z.SharedContactCount)
                .ToList();
        }
    }
公共类测试
{
//模拟一个iquiryable
private readonly IQueryable_people=new List().AsQueryable();
public void FindContactMatchCount(Guid personId)
{
//我们需要用户联系人的id列表进行比较,尽管如此,我们还不需要解决这个问题
//我们将把它作为一个IQueryable,而不是把它变成一个集合
IQueryable idsOfContacts=_people.Where(x=>x.Id==personId)。选择many(x=>x.Contacts.Select(v=>v.Id));
//查找联系人id与联系人id的选定用户列表匹配的所有联系人
//然后投影结果,这个匿名投影有两个属性,person和contact count
var usersWithMatches=\u人
其中(x=>idsOfContacts.Contains(x.Id))
.选择(z=>new
{
Person=z,//这是数据库中的Person记录,我们需要提取显示信息
SharedContactCount=z.Contacts.Count(v=>idsOfContacts.Contains(v.Id))//
}).OrderBy(z=>z.SharedContactCount)
.ToList();
}
}

我建议在您的连接表中添加一些标识字段,使多对多成为一对多和多对一关系,您将能够很好地查询它们。事实上,从来没有真正的多对多关系,因为我们总是有一些额外的属性和联系。例如,关系的创建或更新时间以及状态、活动、阻止等。
public class Test
    {
        //simulate an IQueryable
        private readonly IQueryable<Person> _people = new List<Person>().AsQueryable();

        public void FindContactMatchCount(Guid personId)
        {
            //we'll need the list of id's of the users contacts for comparison, we don't need to resolve this yet though so 
            //we'll leave it as an IQueryable and not turn it into a collection
            IQueryable<Guid> idsOfContacts = _people.Where(x => x.Id == personId).SelectMany(x => x.Contacts.Select(v => v.Id));

            //find all the people who have a contact id that matches the selected users list of contact id's
            //then project the results, this anonymous projection has two properties, the person and the  contact count
            var usersWithMatches = _people
                .Where(x => idsOfContacts.Contains(x.Id))
                .Select(z => new
                    {
                        Person = z, //this is the person record from the database, we'll need to extract display information
                        SharedContactCount = z.Contacts.Count(v => idsOfContacts.Contains(v.Id)) //
                    }).OrderBy(z => z.SharedContactCount)
                .ToList();
        }
    }