我在StackOverflow找到了这段代码:
public static class EntityFrameworkUtil
{
public static IEnumerable<T> QueryInChunksOf<T>(this IQueryable<T> queryable, int chunkSize)
{
return queryable.QueryChunksOfSize(chunkSize).SelectMany(chunk => chunk);
}
public static IEnumerable<T[]> QueryChunksOfSize<T>(this IQueryable<T> queryable, int chunkSize)
{
int chunkNumber = 0;
while (true)
{
var query = (chunkNumber == 0)
? queryable
: queryable.Skip(chunkNumber * chunkSize);
var chunk = query.Take(chunkSize).ToArray();
if (chunk.Length == 0)
yield break;
yield return chunk;
chunkNumber++;
}
}
}
我这样用:
int counter = 0;
foreach (var chunk in _sdb.Posts.OrderBy(c => c.Id).QueryChunksOfSize(100))
{
foreach(var post in chunk)
{
post.Floor= CorrectFloor(post);
post.RealAge= AgeCalculator(post);
post.Area= TerasCheck(post);
_sdb.Entry(post).State = System.Data.Entity.EntityState.Modified;
counter++;
}
_sdb.SaveChanges();
Console.WriteLine("SaveChanges worked, counter : " + counter);
}
此代码应该更新300000行。代码一开始工作得很快,但现在它的工作速度非常慢,并且它在第30000行。你能告诉我为什么这段代码运行缓慢,我怎样才能让它更快?感谢。
答案 0 :(得分:1)
我建议如下:
IQueryable<T>
代替IEnumerable<T>
。使用IEnumerable<T>
将导致对数据库进行的许多查询将降低整体性能。此处OrderBy
子句也没有意义,因为您想要更新所有帖子。检查您的DataContext配置以避免LazyLoading(包括您要加载的属性)和跟踪更改(您也可以按照建议调用AsNoTracking()
):
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.AutoDetectChangesEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
如果此过程需要很长时间才能执行,请确保在async
函数中执行。总结一下,就像这样:
int counter = 0;
foreach (var post in _sdb.Posts.Include("xxx"))
{
post.Floor = CorrectFloor(post);
post.RealAge = AgeCalculator(post);
post.Area = TerasCheck(post);
_sdb.Entry(post).State = System.Data.Entity.EntityState.Modified;
counter++;
}
_sdb.SaveChanges();
Console.WriteLine("SaveChanges worked, counter : " + counter);