我有一个对象列表中的对象列表(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();
}
}
答案 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。希望您的EFDatabase
和EFDatabase2
变量引用同一个数据库中的两个表。
答案 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];
}
在这种情况下,您只需对数据库进行两次查询。