Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.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 SAVECHANGESASSYNC速度极慢_C#_Entity Framework - Fatal编程技术网

C# EF SAVECHANGESASSYNC速度极慢

C# EF SAVECHANGESASSYNC速度极慢,c#,entity-framework,C#,Entity Framework,我有一个表,我想一次更新100行。我有一个100个ID的列表,用于查找特定的行。一旦找到,我会为每一行更新一列(SyncOk) 问题是更新100行大约需要23到30秒 dbContext.Configuration.ValidateOnSaveEnabled = false; var count = ids.Count; for (var i = 0; i < count; i++) { var id = ids[i]; var record = await dbConte

我有一个表,我想一次更新100行。我有一个100个ID的列表,用于查找特定的行。一旦找到,我会为每一行更新一列(SyncOk)

问题是更新100行大约需要23到30秒

dbContext.Configuration.ValidateOnSaveEnabled = false;
var count = ids.Count;
for (var i = 0; i < count; i++)
{
    var id = ids[i];
    var record = await dbContext.History
        .FirstOrDefaultAsync(r => r.Id == id);
    record.SyncOk = syncOk;
}
await dbContext.SaveChangesAsync();
dbContext.Configuration.ValidateOnSaveEnabled=false;
var count=ids.count;
对于(变量i=0;ir.Id==Id);
record.SyncOk=SyncOk;
}
等待dbContext.saveChangesSync();
一些注意事项:

  • ids
    是一个保存所有感兴趣的id的
    IList
  • syncOk
    是一个bool
  • 我试图将
    AutoDetectChangesEnabled
    属性设置为false,然后在设置
    SyncOk
    值之后手动更新记录,但这并没有加快速度

为什么
savechangessync()
速度这么慢-如何提高上述功能的速度?我担心该表在23-30秒内被锁定,并将使其他服务(使用同一个表)也无法更新该表。

您正在对数据库执行总共
id.Count
SELECT语句。如果添加以下代码,则可以看到这一点:

dbContext.Database.Log += Console.WriteLine;
通过一次获取所有数据,尽量减少对SQL实例的访问:

var records = await dbContext.History.Where(i => ids.Contains(i.Id)).ToListAsync();
然后,您应该执行所需的修改:

foreach(var record in records)
{
    record.SyncOk = syncOk;
}
await dbContext.SaveChangesAsync();
您还可以使用
ForEachAsync
,它将像上述代码部分一样只查询一次结果:

await dbContext.History.Where(i => ids.Contains(i.Id))
                       .ForEachAsync(i => i.SyncOk = syncOk);
await dbContext.SaveChangesAsync();

您总共在数据库中执行
id.Count
SELECT语句。如果添加以下代码,则可以看到这一点:

dbContext.Database.Log += Console.WriteLine;
通过一次获取所有数据,尽量减少对SQL实例的访问:

var records = await dbContext.History.Where(i => ids.Contains(i.Id)).ToListAsync();
然后,您应该执行所需的修改:

foreach(var record in records)
{
    record.SyncOk = syncOk;
}
await dbContext.SaveChangesAsync();
您还可以使用
ForEachAsync
,它将像上述代码部分一样只查询一次结果:

await dbContext.History.Where(i => ids.Contains(i.Id))
                       .ForEachAsync(i => i.SyncOk = syncOk);
await dbContext.SaveChangesAsync();

IMHO
从历史记录中选择*,在下面执行(您的列表)
中的Id

var listOfRecordsToBeUpdated = await dbContext.History
        .Where(r => ids.Contains(r.Id)).ToListAsync();

//It will detect the changes each time when you update the entity
// Make sure you re-enable this after your bulk operation
DataContext.Configuration.AutoDetectChangesEnabled = false;

//Iterate through the records and assign your value
listOfRecordsToBeUpdated.Foreach(x=>x.SyncOk = syncOk);

DataContext.Configuration.AutoDetectChangesEnabled = true;

await conn.SaveChangesAsync();

IMHO
从历史记录中选择*,其中(您的列表)
在下面执行

var listOfRecordsToBeUpdated = await dbContext.History
        .Where(r => ids.Contains(r.Id)).ToListAsync();

//It will detect the changes each time when you update the entity
// Make sure you re-enable this after your bulk operation
DataContext.Configuration.AutoDetectChangesEnabled = false;

//Iterate through the records and assign your value
listOfRecordsToBeUpdated.Foreach(x=>x.SyncOk = syncOk);

DataContext.Configuration.AutoDetectChangesEnabled = true;

await conn.SaveChangesAsync();

我尝试实施其他两个答案所建议的更改-但性能结果相同(即速度没有变化)

我通过使用原始SQL命令大大提高了性能(并解决了我的问题):

var stringOfIds = string.Join(",", ids);
await dbContext.Database.ExecuteSqlCommandAsync(
    $"UPDATE dbo.History SET SyncOk = 1 WHERE Id IN ({stringOfIds})");

我试着实现其他两个答案所建议的更改,但性能结果相同(即速度没有变化)

我通过使用原始SQL命令大大提高了性能(并解决了我的问题):

var stringOfIds = string.Join(",", ids);
await dbContext.Database.ExecuteSqlCommandAsync(
    $"UPDATE dbo.History SET SyncOk = 1 WHERE Id IN ({stringOfIds})");

事实并非如此。数据库模式有问题(可能缺少索引?),或者许多其他客户机正在访问同一个表(尽管如此,即使是1秒也会太多)。talbe上是否定义了任何触发器?您是在计时
SaveChanges
本身还是实际执行100次选择的整个代码?@PanagiotisKanavos:计时是执行上述整个代码的持续时间。没有其他客户机使用表atm。让我再与您联系索引。然后,您将对100条单独的FirstOrDefaultAsync语句进行计时,这些语句对应于单个
SELECT TOP 1
查询,而不是SaveChanges。这就是糟糕的SQL。您应该告诉EF加载ID在列表中的所有历史记录项,类似于(…)中的
WHERE x
语句。事实并非如此。数据库模式有问题(可能缺少索引?),或者许多其他客户机正在访问同一个表(尽管如此,即使是1秒也会太多)。talbe上是否定义了任何触发器?您是在计时
SaveChanges
本身还是实际执行100次选择的整个代码?@PanagiotisKanavos:计时是执行上述整个代码的持续时间。没有其他客户机使用表atm。让我再与您联系索引。然后,您将对100条单独的FirstOrDefaultAsync语句进行计时,这些语句对应于单个
SELECT TOP 1
查询,而不是SaveChanges。这就是糟糕的SQL。您应该告诉EF加载ID在列表中的所有历史记录项,类似于(…)中的
WHERE x
语句。