我正在将EF用于一组对象,并希望使用来自另外两个表的匹配条目来查询一种类型的对象。这是将查询转储到XML输出中。首先,使用连接,因为在原始数据中,每个 Employee 总是有1个以上计算机对象的实例(下面的解决方案#2),但它不一定是真的。< / p>
为此目的,想象一下:
所以我看到了几种可能的解决方案:
在循环中使用 Employee.Computer.Load(),但行数超过10,000行会导致性能损失。
在查询中使用 join ,但这会遗漏所有没有计算机的员工。
使用Linq to Entities,但这似乎有#1的开销:当加载计算机时它会触及数据库以获取每个员工 击>
使用第二个查询(所有计算机与 Computer.Employee.Division 匹配),然后在 Employee 循环中,为给定的员工添加任何计算机。实现这一点时,我发现只运行第二个查询(使用 ToList()),EF会使用我需要的对象填充正确的 Employee.Computer 列表。
这里,#4仅使用2个数据库命中而不是10k +加载数据,EntityFramework实际上整理了对象并创建了所有关系。
我的问题 :
更新 : 好吧,开玩笑。对不起,我只是吹了它。我专注于 与“电脑”表的关系,错过了我的事实 有一个明确的 Employee.EmployeeTypeReference.Load()没有第一次测试 对于null,所以“计算机”列表是一个完整的非问题。
我在运行一些性能测试和添加时才发现这一点 克雷格的混合解决方案。事实上,记录不是“员工” 和“计算机”但抽象,我(有条件地)包括每一个 XML输出中的字段,但它们很小:名称,ID(PK)和ID(FK) 加上“员工”表中的INT。所以,我的推测是 由于EF不会创建对象,因此性能会相似 比投影重得多。
无论如何,这是“经过”时间的结果 此查询之前和创建结果XML之后的差异。
案例1:与#2相同,但使用 Include()语句:
list = ve.Employee.Include("Computer").Include("EmployeeType").Where(e => e.Division.ID == divId).OrderBy(e => e.Name);
经历:4.96,5.05
案例2:使用内联加载():
list = ve.Employee.Where(e => e.Division.ID == divId).OrderBy(e => e.Name);
经历:74.62
案例3:与#4相同,但使用 Include()语句:
list = from e in ve.Employee.Include("Computer").Include("EmployeeType")
where e.Division.ID == divId
orderby e.Name select e;
经历:4.91,5.47
案例4:使用内联加载():
list = from e in ve.Employee where e.Division.ID == divId orderby e.Name select e;
经历:74.20
案例5:使用* Include(“EmployeeType”)并单独“计算机”查询,让EF关联:
elist = ve.Employee.Include("EmployeeType").Where(te => te.Division.ID == divId).OrderBy(e => e.Name).ToList();
alist = ve.Alias.Where(a => a.Employee.Division.ID == divId).ToList();
经历:4.50,4.02
案例6:克雷格对预测的建议:
elist = from te in ve.ThesaurusEntry where te.Division.ID==divID
orderby te.Name select new {
ID = te.ID, Name = te.Name,
Type = te.EmployeeType.Name,
Freq = te.Frequency,
Aliases = from a in te.Alias
select new {
ID = a.ID, Name = a.Name
}
};
经历:0.73,1.25
结论
Load()价格昂贵,因此请使用 Include()或至少使用 IsLoaded进行测试
投影有点乏味,但明显快于EF修复。 [对“窄”表进行有限测试]
答案 0 :(得分:2)
我相信你可以表明关系可以预先加载
Dim employees = From emp in db.Employees.Include("Computer") _
Select emp
答案 1 :(得分:1)
Rob的解决方案可以正常工作(+1),但如果您不需要所有字段,例如员工和计算机,我强烈建议投影:
var q = from e in Context.Employees
where e.Division.Id = divisionId
select new
{
Name = e.Name,
EmployeeType = e.EmployeeType.Description,
ComputerIds = from c in e.Computers
select new
{
Id = c.Id
}
};
在这里,您可以在一个查询中获得所需的一切,但不再是:不会返回您不需要的所有字段。
您甚至可以选择XElement
并只保存生成的树而不是手动转换为XML。我没有试过这个,但它似乎应该有效。
关于#4,是的,你可以依赖于此,但在致电IsLoaded
之前检查Load()
总是好的。