我的C#代码中有以下linq查询,这导致System.OutOfmemory excpetion
public SortedSet<string> GetstudentCount()
{
var studentCount= studentRepository
.GetBy(i => i.IsStudentEnabled && i.IsEnrolledAllSubjects)
.AsQueryable()
.AsNoTracking()
.ToList();
var studentSortedSet= new SortedSet<string>();
foreach (var student in studentCount)
{
var id = string.Format("{0}:{1}", student.studentFirstName, student.totalScore);
studentSortedSet.Add(id);
}
return new SortedSet<string>(studentCount);
}
所以我正在尝试对其进行优化,并且可以看到这些选项,但是我不确定,因为在开发数据库中我没有足够的数据来测试。我是Entity Framework和Linq的新手,这让我感到困惑,无法确定哪种方法正确。
1)在Linq查询中删除了ToList()
,但是foreach()
花费的时间与以前相同(仍然很慢)
2)尝试删除整个foreach()
,并在Linq查询本身中添加了Select()
,例如:
public SortedSet<string> GetStudentCount()
{
var studentCount= studentRepository
.GetBy(i => i.IsStudentEnabled &&
i.IsEnrolledAllSubjects)
.Select(string.Format("{0}:{1}",
student.studentFirstName, student.totalScore))
.AsQueryable()
.AsNoTracking()
.ToList();
return new SortedSet<string>(studentCount);
}
但这甚至需要花费相同的时间(仍然很慢)
我进一步想到了在这里删除ToList()
,但是这种方法在很多地方都可以使用(可以确认studentCount
上没有循环),我不确定这是否可能导致更多问题。
关于此的任何建议/建议都更有意义。
EDIT2:
public IEnumerable<T> GetBy(Expression<Func<T, bool>> predicate)
{
return dbSet.Where(predicate);
}
编辑:
对许多人来说,这可能是一个基本问题,我要求他们不要对此问题投反对票,因为在这里,我试图获得一些有关如何优化的建议。这里没有难过的感觉。我正在尝试学习这些知识,如果可以的话,我将不胜感激。谢谢
答案 0 :(得分:2)
您可以做一些优化的事情。但是首先让我们先回顾一些问题。
不要使用存储库anti-pattern,您只是在为实体框架所做的事情编写包装器。
不要将所有内容都拉到内存中,如果遇到内存不足异常(假设您在其他地方的代码中没有做错任何事情),则将太多数据拉到内存中,如果需要提取那么多数据。创建一个paging api。
仅从数据库中选择所需的数据。正如您已经发现的那样,仅在需要“名字”和“总分”时撤回整个数据集是一种浪费。
选择更好的数据结构。没有理由使用一组排序的字符串。同样非常令人怀疑的是,您会得到想要的结果,因为得分低一位数的人的排名会更高,因为您使用的是alpha排序,例如
Andy:93
Andy:8
Andy:79
您的排序可能应该在SQL端完成 当所有这些都完成后,您应该有一个类似于以下内容(减去分页):
public class StudentScores
{
public string Name { get; set;}
public string TotalScore {get; set; }
}
var results = dbContext.Students.AsNoTracking().Where(s => s.IsStudentEnabled
&& s.IsEnrolledAllSubjects)
.OrderBy(x => x.studentFirstName).ThenBy(x => x.totalScore)
.Select(x => new StudentScores {
Name = x.studentFirstName,
TotalScore = x.totalScore
}).ToList();
您还可以进行其他微优化,例如编译后的查询,但Id只是从现在开始。
(PS。我的主要猜测是错误是由于您没有向我们显示某些内容,似乎您没有向我们显示完整代码,因为此行中的学生变量来自何处
.Select(string.Format("{0}:{1}", student.studentFirstName, student.totalScore))
答案 1 :(得分:2)
YourFunction(...,int pageSize = 50, int page = 0)
,然后是Get(...).Skip(pageSize *page).Take(pageSize)
。没有页面将显示100多个结果Parallel query
和yield return