我有一个LINQ查询,它获取嵌套对象列表。
from c in ClientsRepository.LoadAll()
orderby c.Name
select new ComboBoxOptionGroup
{
Text = c.Name,
Options = from p in c.Projects
orderby p.Name
select new ComboBoxOption
{
Text = p.Name,
Value = p.ID.ToString()
}
}
不幸的是,这个LINQ查询导致num(客户端)+1 SQL查询。有没有任何优雅的方法来重写它,以便它只导致一个SQL查询?
我的想法是获取客户订购的所有项目,并在两个嵌套的foreach循环中完成剩下的工作,但这似乎违背了LINQ设计时的优雅。还有更好的选择吗?
答案 0 :(得分:2)
如果ClientsRepository.LoadAll()
是查询的包装器,它实际上会进入数据库并检索数据(不返回IQueryable<T>
),那么就会被卡住。如果它返回一个查询的一部分(确实返回IQueryable<T>
)那么它应该是可能的。
但是,如果不知道数据(或对象)上下文的位置和模型,则很难。
通常情况下,我希望做类似的事情:
from client in dataContext.Clients
join p in dataContext.Projects on p.ClientId equals c.Id
into projects
orderby client.Name
select new ComboBoxOptionGroup {
Text = client.Name,
Option = from p in projects
orderby p.Name
select new ComboBoxOption {
Text = p.Name,
Value = p.ID.ToString()
}
}
答案 1 :(得分:2)
另一种可能的替代方法是使用DataLoadOptions
。
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Client>(c => c.Projects);
context.DeferredLoadingEnabled = false; // You may not need/want this line
context.LoadOptions = dlo;
我没有测试过这种做法,但您希望能够单独留下查询并减少必要查询的数量。
答案 2 :(得分:1)
您可能会搜索“加入”运算符:http://www.hookedonlinq.com/JoinOperator.ashx