在C#中的列表中填充列表而不使用foreach循环。更好的方法?

时间:2016-05-13 15:15:14

标签: c# .net entity-framework linq list

我有一个对象列表中的对象列表(List-ParentClass),它的对象之一是嵌套列表(List-ChildClass)。为了填充List-ChildClass,我使用了一个foreach循环,如下所示。我还嵌套了一个linq查询,如下所示。

此时我遇到了一些性能问题,我觉得有一种更好的方法可以解决这个问题。

问题:我怎样才能更好/更快地做到这一点?

注意 - 这是一个用C#编写的基于Web的.net MVC应用程序。我使用EF回到SQL数据库。

public class ParentClass
{
    public int pcid { get; set; }
    public List<ChildClass> ChildClassList { get; set; }
}

public class ChildClass
{
    public int pcid { get; set; }
    public int ccid { get; set; }
}

public class DoWork 
{
    public void ExampleMethodForEach()
    {
        List<ParentClass> ParentClassList = new List<ParentClass>();

        foreach(ParentClass a in ParentClassList)
        {
            a.ChildClassList = EFDatabase2.where(b => b.pcid == a.pcid).select(b => b.ccid).ToList();
        }
    }

    public void ExampleMethodLinq()
    {
        var ParentClassList = (from a in EFDatabase
                               select new ParentClass
                               {
                                   ccid = a.ccid,
                                   pcid = (from b in EFDatabase2
                                           where b.pcid == a.pcid
                                           select b.ccid).ToList()
                                   //something like this were I nest a query
                               }).ToList();
    }
}

2 个答案:

答案 0 :(得分:2)

使用关系数据库和LINQ时,最好的方法是使用连接来关联数据。在您的情况下,最合适的是group join

var ParentClassList =
    (from p in EFDatabase
     join c in EFDatabase2 on p.pcid equals c.pcid into children
     select new ParentClass
     {
         pcid = p.pcid,
         ChildClassList =
             (from c in children
              select new ChildClass
              {
                  pcid = c.pcid,
                  ccid = c.ccid
              }).ToList()
     }).ToList();

这应该可以为您提供快速的单一数据库查询。

P.S。希望您的EFDatabaseEFDatabase2变量引用同一个数据库中的两个表。

答案 1 :(得分:0)

您多次访问数据库。你有一个N + 1问题。

我建议首先查询所有父母,但不包括子项数据。然后获取您检索到的所有父项的ID并将其放入数组中。我们将使用该数组在SQL中创建一个IN子句。

使用父ID数组加载所有子项后,使用父ID作为键将ToLookup映射到查找,并使用foreach将子项列表分配给父项。

var parents = EFDatabase2.Parents.Where(...).Select(p => new ParentClass { pcid = p.pcid }).ToList();
var ids = parents.Select(p => p.pcid).ToArray();
var children = EFDatabase2.Children.Where(c => ids.Contains(c.ccid)).Select(c => new ChildClass { pcid = c.pcid, ccid = c.ccid }).ToLookup(c => c.pcid);

foreach (var parent in parents)
{
    parent.Children = children[parent.pcid];
}

在这种情况下,您只需对数据库进行两次查询。