Linq:将1个子集合与(聚合)ChildCollection进行比较

时间:2014-09-10 20:18:05

标签: c# linq

我有一个Linq问题:(DotNet Framework 4.0)

我有以下课程:

public class Employee
{
    public Guid? EmployeeUUID { get; set; }
    public string SSN { get; set; }
}

public class JobTitle
{
    public Guid? JobTitleSurrogateKey { get; set; }
    public string JobTitleName { get; set; }
}


public class EmployeeToJobTitleMatchLink
{
    public EmployeeToJobTitleMatchLink()
    {
        this.TheJobTitle = new JobTitle() { JobTitleSurrogateKey = Guid.NewGuid(), JobTitleName = "SomeJobTitle:" + Guid.NewGuid().ToString("N") };
    }
    public Guid LinkSurrogateKey { get; set; }
    /* Related Objects */
    public Employee TheEmployee { get; set; }
    public JobTitle TheJobTitle { get; set; }
}


public class Organization
{
    public Organization()
    {
        this.Links = new List<EmployeeToJobTitleMatchLink>();
    }

     public int OrganizationSurrogateKey { get; set; }

    public ICollection<EmployeeToJobTitleMatchLink> Links { get; set; }
}

在下面的代码中,我可以比较2个子集合并获得我需要的结果(在“matches1”中)。 这里我使用“SSN”字符串属性来比较和查找重叠。而Match1的match.Write就像我期望的那样工作。

我不知道怎么做是将第一个子集合(org10)与所有子集(allOtherOrgsExceptOrg10(所有组织和这些组织的所有链接)进行比较

注释掉的代码显示了我正在尝试做的事情,这是我今天许多虚弱的尝试之一。

但基本上,match2将填充所有SSN重叠...但将org10与allOtherOrgsExceptOrg10,所有“链接”及其Employee.SSN进行比较。 org10与org20重叠为“AAA”,因此match2将包含“AAA”。和org10与org30重叠,带有“BBB”,因此match2将包含“BBB”。

            Organization org10 = new Organization();
            org10.OrganizationSurrogateKey = 10;

            Employee e11 = new Employee() { SSN = "AAA", EmployeeUUID = new Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA") };
            EmployeeToJobTitleMatchLink link11 = new EmployeeToJobTitleMatchLink();
            link11.TheEmployee = e11;

            org10.Links.Add(link11);

            Employee e12 = new Employee() { SSN = "BBB", EmployeeUUID = new Guid("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB") };
            EmployeeToJobTitleMatchLink link12 = new EmployeeToJobTitleMatchLink();
            link12.TheEmployee = e12;

            org10.Links.Add(link12);



            Organization org20 = new Organization();
            org20.OrganizationSurrogateKey = 20;

            Employee e21 = new Employee() { SSN = "AAA", EmployeeUUID = new Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA") };
            EmployeeToJobTitleMatchLink link21 = new EmployeeToJobTitleMatchLink();
            link21.TheEmployee = e21;

            org20.Links.Add(link21);

            Employee e22 = new Employee() { SSN = "CCC", EmployeeUUID = new Guid("CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC") };
            EmployeeToJobTitleMatchLink link22 = new EmployeeToJobTitleMatchLink();
            link22.TheEmployee = e22;

            org20.Links.Add(link22);



            Organization org30 = new Organization();
            org30.OrganizationSurrogateKey = 30;

            Employee e31 = new Employee() { SSN = "BBB", EmployeeUUID = new Guid("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB") };
            EmployeeToJobTitleMatchLink link31 = new EmployeeToJobTitleMatchLink();
            link31.TheEmployee = e31;

            org30.Links.Add(link31);

            Employee e32 = new Employee();
            e32.SSN = "ZZZ";
            EmployeeToJobTitleMatchLink link32 = new EmployeeToJobTitleMatchLink();
            link32.TheEmployee = e32;

            org30.Links.Add(link32);


            IList<Organization> allOtherOrgsExceptOrg10 = new List<Organization>();

            /* Note, I did not add org10 here */
            allOtherOrgsExceptOrg10.Add(org20);
            allOtherOrgsExceptOrg10.Add(org30);


            IEnumerable<EmployeeToJobTitleMatchLink> matches1 =
            org10.Links.Where(org10Link => org20.Links.Any(org20Link => org20Link.TheEmployee.SSN.Equals(org10Link.TheEmployee.SSN, StringComparison.OrdinalIgnoreCase)));


            IEnumerable<EmployeeToJobTitleMatchLink> matches2 = null;
            //org10.Links.Where(org10Link  =>  ( allOtherOrgs.Where ( anyOtherOrg  => anyOtherOrg.Links.Any(dbSideChild => dbSideChild.TheEmployee.SSN == org10Link.TheEmployee.SSN)) );


            if (null != matches1)
            {
                foreach (EmployeeToJobTitleMatchLink link in matches1)
                {
                    Console.WriteLine(string.Format("matches1, SSN = {0}", link.TheEmployee.SSN));
                }
            }

            if (null != matches2)
            {
                foreach (EmployeeToJobTitleMatchLink link in matches2)
                {
                    Console.WriteLine(string.Format("matches2, SSN = {0}", link.TheEmployee.SSN));
                }
            }

2 个答案:

答案 0 :(得分:1)

您可以使用SelectMany来展平集合,然后像使用match1一样使用它

IEnumerable<EmployeeToJobTitleMatchLink> matches2 =
            org10.Links.Where(
                org10Link =>
                allOtherOrgsExceptOrg10.SelectMany(allOtherOrgs => allOtherOrgs.Links).Any(
                    anyOtherLink =>
                    anyOtherLink.TheEmployee.SSN.Equals(org10Link.TheEmployee.SSN, StringComparison.OrdinalIgnoreCase)));

SelectMany将使它看起来像一个IEnumerable而不是IEnumerable的IEnumerable。

答案 1 :(得分:1)

matches2 =
            allOtherOrgsExceptOrg10.SelectMany(x => x.Links)
                .Where(x => org10.Links.Select(o => o.TheEmployee.SSN).Contains(x.TheEmployee.SSN));

您可以使用allOther集合上的SelectMany选择所有组织上的所有链接。然后检查org10列表中是否有任何SSN。

请参阅:http://msdn.microsoft.com/en-us/library/system.linq.enumerable.selectmany(v=vs.100).aspx