EF 更新大量的数据时出现重复键错误
生活随笔
收集整理的這篇文章主要介紹了
EF 更新大量的数据时出现重复键错误
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
咨詢區
ChsharpNewbie:
當我把大量的數據插入到數據庫時 (PostgreSQL 12 和 Entity Framework Core),我得到了如下的報錯。
fail:?Microsoft.EntityFrameworkCore.Database.Command[20102]Failed?executing?DbCommand?(197ms)?[Parameters=[@p0='?',?@p1='?',?@p2='?'?(DbType?=?DateTimeOffset),?@p3='?'],?CommandType='Text',?CommandTimeout='30']INSERT?INTO?"FileInfos"?("FileId",?"FileName",?"LastModifiedDateTime",?"Path")VALUES?(@p0,?@p1,?@p2,?@p3); fail:?Microsoft.EntityFrameworkCore.Update[10000]An?exception?occurred?in?the?database?while?saving?changes?for?context?type?'PostgreSQLConnect.ContextModels.WebhookContext'.Microsoft.EntityFrameworkCore.DbUpdateException:?An?error?occurred?while?updating?the?entries.?See?the?inner?exception?for?details.--->?Npgsql.PostgresException?(0x80004005):?23505:?duplicate?key?value?violates?unique?constraint?"PK_FileInfos?Severity:?FEHLERSqlState:?23505MessageText:?double?key?value?violates?unique?constraint??PK_FileInfos?Detail:?Detail?redacted?as?it?may?contain?sensitive?data.?Specify?'Include?Error?Detail'?in?the?connection?string?to?include?this?information.SchemaName:?publicTableName:?FileInfosConstraintName:?PK_FileInfosFile:?d:\pginstaller_12.auto\postgres.windows-x64\src\backend\access\nbtree\nbtinsert.cLine:?570Routine:?_bt_check_unique這其中一些數據需要被更新,一些數據需要被創建,在一定數據量下這個方法比較穩定,但如果超過閾值后就會拋出如上的錯誤,我的代碼如下:
private?async?Task?SaveFileInfos(FileInfo?fileInfo){var?foundFileInfo?=?_context.FileInfos.Where(f?=>?f.FileId?==?fileInfo.FileId).FirstOrDefault();if?(foundFileInfo?==?null){await?_context.FileInfos.AddAsync(fileInfo);}else{foundFileInfo.FileName?=?fileInfo.FileName;foundFileInfo.LastModifiedDateTime?=?fileInfo.LastModifiedDateTime;foundFileInfo.Path?=?fileInfo.Path;}await?_context.SaveChangesAsync();}我的類定義如下:
public?class?FileInfo?:?IFileInfo{[Key]public?string?FileId?{get;?set;}public?string?FileName?{get;?set;}public?DateTimeOffset??LastModifiedDateTime?{get;?set;}public?string?Path?{get;?set;}}Context類如下:
public?class?WebhookContext?:?DbContext{public?WebhookContext(DbContextOptions<WebhookContext>?options)?:?base(options)?{?}public?DbSet<FileInfo>?FileInfos?{?get;?set;?}}然后在 loop 中做數據庫保存。
private?async?Task?ConvertAndSaveFiles(IDriveItemDeltaCollectionPage?files){?foreach?(var?file?in?files){await?SaveFileInfos(file.Name,?file.Id,?file.LastModifiedDateTime,?file.ParentReference.Path);}}請問我這是哪里寫的有問題?
回答區
Edd:
我覺得你要做兩點修改。
將 FirstOrDefault 改成 FirstOrDefaultAsync。
where 查詢也是多余的。
改造后如下:
private?async?Task?SaveFileInfos(FileInfo?fileInfo){//update?your?code?to?use?FirstOrDefaultAsyncvar?foundFileInfo?=?await?_context.FileInfos.FirstOrDefaultAsync(f?=>?f.FileId?==?fileInfo.FileId);if?(foundFileInfo?==?null){await?_context.FileInfos.AddAsync(fileInfo);}else{foundFileInfo.FileName?=?fileInfo.FileName;foundFileInfo.LastModifiedDateTime?=?fileInfo.LastModifiedDateTime;foundFileInfo.Path?=?fileInfo.Path;}//?move?this?outside?the?for?loop.//?this?will?round?trip?to?Db?in?EVERY?fileInfo,?not?an?optimal?solution.await?_context.SaveChangesAsync();?}考慮到 SaveChangesAsync 是序列化到數據庫,可以移到循環體外。
private?async?Task?ConvertAndSaveFiles(IDriveItemDeltaCollectionPage?files){?foreach?(var?file?in?files){await?SaveFileInfos(file.Name,?file.Id,?file.LastModifiedDateTime,?file.ParentReference.Path);}//?this?will?save?everything?to?Db?in?just?1?round?tripawait?_context.SaveChangesAsync();?}點評區
我個人感覺,這里報錯的原因是: 本應該全異步的寫法里面又摻雜了同步的寫法,這是一種很雞肋的做法,數據量稍微大一些之后就會有各種問題,這也是一個好的經驗教訓。
總結
以上是生活随笔為你收集整理的EF 更新大量的数据时出现重复键错误的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 记一次 .NET 某上市工业智造 CPU
- 下一篇: 利用Azure communicatio