使用LINQ的“into”关键字对连接进行分组,而不是返回集合

时间:2017-08-22 17:43:35

标签: c# mysql sql-server linq join

所以我对LINQ很新,遇到了一个我无法找到解决方案的问题。

当我看到有关Group Joins的文章时,我正在阅读msdn上的LINQ指南。

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

我通读了这个页面并认为这正是我完成查询所需要的。对于我的查询,我正在调用表A,其中包含我用来与联系人表联接的ID。然后,来自联系人表的ID用于在相同的ID上与表C连接。表C包含一个子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();
    }
}

1 个答案:

答案 0 :(得分:0)

尝试拔出联系人并使用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
             });

注意,对Distinct运行PrimaryID然后查找FirstNameLastName可能会更好,但这应该在SQL端运行,所以我不认为这很重要。