Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用EF和块更新数据库运行非常缓慢_C#_Sql_Entity Framework_Linq - Fatal编程技术网

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
    子句在这里没有意义,因为您想更新所有帖子

  • 调用SaveChanges一次。您的示例将每100个元素提交一次更改

  • 查看DataContext配置以避免懒散加载(包括要加载的属性)和跟踪更改(您也可以按建议调用
    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);