c# - 使用LINQ的 "into"关键字进行分组连接不返回集合

标签 c# mysql sql-server linq join

所以我对 LINQ 相当陌生,并且遇到了一个我无法找到解决方案的问题。

当我阅读 msdn 上的 LINQ 指南时,看到一篇关于 Group Joins 的文章。

https://learn.microsoft.com/en-us/dotnet/csharp/linq/perform-grouped-joins

我通读了该页面,并认为这正是我完成查询所需要的。对于我的查询,我调用表 A,其中包含我用来连接联系人表的 ID。然后使用联系人表中的 ID 与具有相同 ID 的表 C 进行连接。表 C 保存一个子 ID,然后使用该 ID 与联系人表连接以检索联系人列表。联系人主要 ID 用于与电话号码表连接。联系人可以有多个电话号码。

var query = (from a in db.TableA
                     join b in db.Contacts on a.PrimaryID equals b.PrimaryID
                     join c in db.tableC on b.PrimaryID equals c.ParentPrimaryID
                     join d in db.Contacts on c.ChildID equals d.PrimaryID
                     join e in db.TablePhoneNbrs on d.PrimaryID equals e.PrimaryID into gj
                     where a.PrimaryID == id
                     select new
                     {
                         PrimaryId = d.PrimaryId,
                         FirstName = d.FirstName,
                         LastName = d.LastName,
                         phhoneNbrs = gj
                     });

因此,从文章中,我读到,如果您连接两个表,然后在连接后调用“into”,它将把查询结果存储到您指定为集合的任何变量中。因此,在上面的查询中,我尝试将各个联系人与其单个/多个电话号码连接起来,然后调用“into”返回一个集合,而不是复制每个号码的联系人,但失败了。它不是返回具有多个号码的联系人的电话号码集合,而是只是为返回的每个号码复制联系人。

因此,我尝试减少查询,转而使用特定的联系人 ID 号码,并仅使用单个结果进行测试。

var query2 = (from a in db.Contacts
     join b in db.TablePhoneNbrs on a.PrimaryID equalsb.PrimaryID into gj
     where a.PrimaryID == 1234
     select new
     {
         PrimaryID = a.PrimaryID,
         FirstName = a.FirstName,
         LastName = a.LastName,
         phhoneNbrs = gj
      }).ToList();

这成功了!因此,当我使用单个联系人 ID 执行查询时,它正确地将联系人及其两个电话号码作为附加到一个联系人对象的数组返回。

我的问题是我在第一个查询中是否做错了什么导致它失败?

更新:有一个更好的例子! 这几乎就是关系与表的工作方式。不过,这个例子似乎有效。 Query2 是我工作中最失败的一个。当它返回联系人时,它不会将号码存储在集合中并将其分配给 Number 变量,而是为其拥有的每个号码复制联系人。

class Contact
{
    public int primaryID { get; set; }
    public string name { get; set; }
}

class TableC
{
    public int parentID { get; set; }
    public int childID { get; set; }
}

class TablePhoneNbr
{
    public int primaryID { get; set; }
    public string phoneNbr { get; set; }
}

class TableEmail
{
    public int primaryID { get; set; }
    public string email { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Contact mainContact = new Contact { primaryID = 1, name = "My Test Code" };
        Contact Jim = new Contact { primaryID = 2, name = "Jim" };
        Contact Bob = new Contact { primaryID = 3, name = "Bob" };
        Contact Ashley = new Contact { primaryID = 4, name = "Ashley" };
        Contact Mary = new Contact { primaryID = 5, name = "Mary" };

        TableC child1 = new TableC { parentID = 1, childID = 2 };
        TableC child2 = new TableC { parentID = 1, childID = 3 };
        TableC child3 = new TableC { parentID = 1, childID = 4 };
        TableC child4 = new TableC { parentID = 1, childID = 5 };

        TablePhoneNbr Nbr1 = new TablePhoneNbr { primaryID = 2, phoneNbr = "123456" };
        TablePhoneNbr Nbr2 = new TablePhoneNbr { primaryID = 2, phoneNbr = "999999" };
        TablePhoneNbr Nbr3 = new TablePhoneNbr { primaryID = 3, phoneNbr = "888888" };
        TablePhoneNbr Nbr4 = new TablePhoneNbr { primaryID = 4, phoneNbr = "777777" };

        TableEmail Email1 = new TableEmail { primaryID = 2, email = "Hello World" };
        TableEmail Email2 = new TableEmail { primaryID = 3, email = "Goodbye World" };
        TableEmail Email3 = new TableEmail { primaryID = 4, email = "Testing1" };
        TableEmail Email4 = new TableEmail { primaryID = 5, email = "Testing2" };

        // Create two lists.
        List<Contact> contacts = new List<Contact> { mainContact, Jim, Bob, Ashley, Mary };
        List<TableC> relations = new List<TableC> { child1, child2, child3, child4 };
        List<TablePhoneNbr> numbers = new List<TablePhoneNbr> { Nbr1, Nbr2, Nbr3, Nbr4 };
        List<TableEmail> emails = new List<TableEmail> { Email1, Email2, Email3, Email4 };

        // Create a list where each element is an anonymous type
        // that contains the person's first name and a collection of 
        // pets that are owned by them.
        var query = from primary in contacts
                    join relation in relations on primary.primaryID equals relation.parentID
                    join person in contacts on relation.childID equals person.primaryID
                    join number in numbers on person.primaryID equals number.primaryID into gj
                    select new { FirstName = person.name, Number = gj };

        foreach (var v in query)
        {
            // Output the owner's name.
            Console.WriteLine("{0}:", v.FirstName);
            // Output each of the owner's pet's names.
            foreach (TablePhoneNbr number in v.Number)
                Console.WriteLine("  {0}", number.phoneNbr);
        }

        var query2 = from primary in contacts
                    join relation in relations on primary.primaryID equals relation.parentID
                    join person in contacts on relation.childID equals person.primaryID
                    join email in emails on person.primaryID equals email.primaryID
                    join number in numbers on person.primaryID equals number.primaryID into gj
                    select new { FirstName = person.name, Number = gj, Email = email.email };

        foreach (var v in query2)
        {
            // Output the owner's name.
            Console.WriteLine("{0}:", v.FirstName);
            Console.WriteLine("{0}:", v.Email);
            // Output each of the owner's pet's names.
            foreach (TablePhoneNbr number in v.Number)
                Console.WriteLine("  {0}", number.phoneNbr);
        }
        Console.ReadLine();
    }
}

最佳答案

在尝试获取联系人号码之前,请尝试取出您的联系人并使用 Distinct():

var contacts = (from a in db.TableA
                where a.PrimaryID == id
                join b in db.Contacts on a.PrimaryID equals b.PrimaryID
                join c in db.tableC on b.PrimaryID equals c.ParentPrimaryID
                join d in db.Contacts on c.ChildID equals d.PrimaryID
                select new { d.PrimaryID, d.FirstName, d.LastName } ).Distinct();

var query = (from d in contacts
             join e in db.TablePhoneNbrs on d.PrimaryID equals e.PrimaryID into ej
             select new {
                 PrimaryId = d.PrimaryID,
                 FirstName = d.FirstName,
                 LastName = d.LastName,
                 phhoneNbrs = ej
             });

请注意,最好针对 PrimaryID 运行 Distinct,然后查找 FirstNameLastName,但它应该在 SQL 端运行,所以我认为这并不重要。

关于c# - 使用LINQ的 "into"关键字进行分组连接不返回集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45823904/

相关文章:

c# - 如何在 Entity Framework 中包含排序的导航属性

c# - 循环列表空元素

sql-server - SQL - 从合并查询过滤器获取数据库名称

SQL:row_number:按日期排序,最后需要 Null

java - 使用 Hibernate 将 csv 文件导入 MySQL 数据库

sql - 在 T-SQL 查询中,仅需要获取根元素的属性名称-值对

c# - ASP.Net c# 选择了给定 GroupName 中的哪个单选按钮?

c# - 从 iframe 中的页面检索 session 的 PageMethods 不起作用

php - jQuery 向 php 发送多个需求

java - 获取查询更新的行的 ID