我有以下LINQ查询:
//two different contexts, databases, tables...
NoteSet = lmCtx.LMNotes.AsEnumerable();
EmpSet = tessCtx.Employees.AsEnumerable();
var lmAccountNotes = (from lmnote in NoteSet
join createdby in EmpSet on lmnote.lnt_createdById equals createdby.EmployeeID
join modifiedby in EmpSet on lmnote.lnt_modifiedById equals modifiedby.EmployeeID
where lmnote.lnt_recordId == 5566 && lmnote.lnt_tableId == 1
select new NoteInfo { Note = lmnote, CreatedBy = createdby, ModifiedBy = modifiedby }).ToList();
这适用于小型表的查询,但是NoteSet
是一个非常大的表,并且在框架爆炸之前我已经达到了超过1.5GB的已用内存并抛出{{1}例外。
在执行类似的操作时,有没有办法保持延迟加载功能?
答案 0 :(得分:0)
为了继续使用返回NoteInfo
对象的查询,我将其更改为:
//LMNotes is the actual huge database...
var m = lmCtx.LMNotes.Where(x => x.lnt_recordId == 5566).ToList();
var lmAccountNotes = (from lmnote in m
join createdby in EmpSet on lmnote.lnt_createdById equals createdby.EmployeeID
join modifiedby in EmpSet on lmnote.lnt_modifiedById equals modifiedby.EmployeeID
where lmnote.lnt_recordId == 566 && lmnote.lnt_tableId == 1
select new NoteInfo { Note = lmnote, CreatedBy = createdby, ModifiedBy = modifiedby }).ToList();
这是更好的
答案 1 :(得分:0)
正如评论中所解释的那样,你不能真正在两个不同的数据库中运行单个查询,至少在没有设置一些帮助构造的情况下(它们将存在于任一数据库中,实际上谁知道这是否会提高性能)全部)。
但是,这并不意味着我们根本无法改进您的查询。如果我们不能依赖数据库引擎来执行查询,我们可以自己做。在这种情况下,您所做的只是对LMNotes
实体的查询,然后您从Employees
集合加入员工。
所以天真的解决方案可能如下所示:
var notes = lmCtx.LMNotes
.Where(lmnote => lmnote.lnt_recordId == 5566 && lmnote.lnt_tableId == 1)
.Select(lmnote =>
{
return new NoteInfo
{
Note = lmnote,
CreatedBy = tessCtx.Employees.FirstOrDefault(e => e.EmployeeId == lmnote.lnt_createdById),
ModifiedBy = tessCtx.Employees.FirstOrDefault(e => e.EmployeeId == lmnote.lnt_modifiedById)
};
})
.ToList();
当然,虽然这会在LMNotes
上运行单个查询,但仍会对结果中的每个注释运行两个单独的查询。所以它并不比EF在那里做的好。
然而,我们可以做的是添加一些查找。我怀疑这组员工有点受限,所以只收取每位员工一次是有意义的。像这样:
private Dictionary<int, Employee> employees = new Dictionary<int, Employee>();
private Employee GetEmployee(int employeeId)
{
Employee employee;
if (!employees.TryGetValue(employeeId, out employee))
{
employee = tessCtx.Employees.FirstOrDefault(e => e.EmployeeId == employeeId);
employees[employeeId] = employee;
}
return employee;
}
public List<NoteInfo> GetNotes()
{
return lmCtx.LMNotes
.Where(lmnote => lmnote.lnt_recordId == 5566 && lmnote.lnt_tableId == 1)
.Select(lmnote =>
{
return new NoteInfo
{
Note = lmnote,
CreatedBy = GetEmployee(lmnote.lnt_createdById),
ModifiedBy = GetEmployee(lmnote.lnt_modifiedById)
};
})
.ToList();
}
这只会查找每个员工一次,然后缓存员工对象。
或者,您也可以在此处进行第二次传递,并在第一次阅读笔记后立即获取所有员工。像这样:
public List<NoteInfo> GetNotes()
{
var employeeIds = new HashSet<int>();
var notes = lmCtx.LMNotes
.Where(lmnote => lmnote.lnt_recordId == 5566 && lmnote.lnt_tableId == 1)
.Select(lmnote =>
{
// remember the ids for later
employeeIds.Add(lmnote.lnt_createdById);
employeeIds.Add(lmnote.lnt_modifiedById);
return new NoteInfo
{
Note = lmnote,
CreatedBy = null,
ModifiedBy = null
};
})
.ToList();
var employees = tessCtx.Employees
.Where(e => employeeIds.Contains(e.EmployeeId))
.ToList()
.ToDictionary(e => e.EmployeeId);
foreach (var noteInfo in notes)
{
noteInfo.CreatedBy = employees[noteInfo.Note.lnt_createdById];
noteInfo.ModifiedBy = employees[noteInfo.Note.lnt_modifiedById];
}
return notes;
}
这只会对每个数据库运行一次查询。