C# 使用EF和块更新数据库运行非常缓慢
我在以下网站上找到了此代码:C# 使用EF和块更新数据库运行非常缓慢,c#,sql,entity-framework,linq,C#,Sql,Entity Framework,Linq,我在以下网站上找到了此代码: 这段代码应该更新300000行。代码起初运行得很快,但现在运行得很慢,位于第30000行。你能告诉我为什么这段代码运行缓慢,我怎样才能使它更快?谢谢。我推荐如下: 使用IQueryable而不是IEnumerable。使用IEnumerable将导致对数据库执行许多查询,从而降低总体性能。另外,OrderBy子句在这里没有意义,因为您想更新所有帖子 调用SaveChanges一次。您的示例将每100个元素提交一次更改 查看DataContext配置以避免懒散加载
这段代码应该更新300000行。代码起初运行得很快,但现在运行得很慢,位于第30000行。你能告诉我为什么这段代码运行缓慢,我怎样才能使它更快?谢谢。我推荐如下:
IQueryable
而不是IEnumerable
。使用IEnumerable
将导致对数据库执行许多查询,从而降低总体性能。另外,OrderBy
子句在这里没有意义,因为您想更新所有帖子
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);
我想这就是问题所在。但通常可以通过在循环外调用SaveChanges来提高性能。@Emad对整个数据库调用SaveChanges是个好主意吗?我认为
SaveChanges()
当前位于正确的位置,因为它在每100个项目后保存一次(尽管我会将其增加到1000个)。我怀疑经济放缓与变化跟踪有关。我不是EF方面的专家,但我认为使用AsNoTracking()
会有所帮助<第一个foreach中的_sdb.Posts.AsNoTracking().OrderBy(c=>c.Id).QueryChunksOfSize(100))中的代码>变量块。对于初学者,请删除\u sdb.Entry(post).State=System.Data.Entity.EntityState.Modified代码>。没有必要将整个记录标记为已修改。我认为OrderBy是必要的。否则,您无法保证每个查询都具有相同的顺序(几乎可以肯定,但查询计划可能会更改)。另外,如果id是一个标识列,那么我们知道任何新记录都会出现在末尾。这样可以避免先获取100条记录,然后再插入一条新记录。
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);
}
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);