我有以下代码:
public List<NoteViewModel> GetAllPerContacts(List<long> contactIds)
{
// This next line causes a stack overflow
var contacts = _unitOfWork.ContactRepository.GetQuery()
.IncludeMultiple(x => x.Notes)
.Where(x => contactIds.Any(y => y == x.Id))
.ToList();
var noteModels = contacts.SelectMany(x => x.Notes.Select(n => GetNoteModel(n)));
return noteModels.ToList();
}
如果有大约3000条记录,则第一条语句会导致堆栈溢出。如果删除.Where行,或者记录较少,则运行正常。
有没有更好的方法来执行.Any不会导致堆栈溢出?
根据要求:
public static IQueryable<T> IncludeMultiple<T>(this IQueryable<T> query,
params Expression<Func<T, object>>[] includes) where T : class
{
if (includes != null)
{
query = includes.Aggregate(query,
(current, include) => current.Include(include));
}
return query;
}
答案 0 :(得分:0)
翻译的sql的大小有限制。所以如果有大量contactIds
翻译的sql会太大。解决方法是将contactIds拆分为较小的列表并合并结果。像这样:
public List<NoteViewModel> GetAllPerContacts(List<long> contactIds)
{
var query = _unitOfWork.ContactRepository.GetQuery().IncludeMultiple(x => x.Notes);
IEnumerable<Contact> contacts = Enumerable.Empty<Contact>();
long increment = 100;
long groups = contactIds.Count / increment + 1;
for(int i=0; i<groups; i++)
{
List<long> partialIds = contactIds.Skip(i*increment).Take(increment).ToList();
contacts = contacts.Concat(query.Where(x => partialIds.Any(y => y == x.Id)).ToList());
}
var noteModels = contacts.SelectMany(x => x.Notes.Select(n => GetNoteModel(n)));
return noteModels.ToList();
}
答案 1 :(得分:0)
我忽略了一个非常简单的解决方案......使用.Contains函数。
我将代码修改为:
var contacts = _unitOfWork.ContactRepository.GetQuery()
.IncludeMultiple(x => x.Notes)
.Where(x => contactIds.Contains(x.Id))
.ToList();
它完美无缺。