我在測驗環境中收到錯誤,但在 prod 環境中沒有收到錯誤,即使沒有放置跟蹤也是如此。
錯誤“GetUserAsync:System.InvalidOperationException:無法跟蹤物體型別‘UserEntity’的實體,因為另一個具有鍵值‘{Id:1}’的實體已被跟蹤。附加現有物體時,請確保只有一個物體實體具有附加了給定的鍵值。
代碼:
internal async Task<UserEntity> GetUserAsync(CancellationToken cancellationToken)
{
var result = await _userDataQuery.GetLatestUser(cancellationToken);
}
我已經添加了AsNoTracking:
public async Task<UserEntity> GetLatestUser(CancellationToken cancellationToken)
{
var result = await this.Entities
.OrderByDescending(m => m.Id)
.AsNoTracking().FirstOrDefaultAsync();
await Context.Entry(result).ReloadAsync();
return result;
}
不確定這是否有幫助,但我也注意到兩個環境之間 postgreSQL 上的 pg_sequences 對于用戶表是不同的,并且它們都在表中只有 1 條記錄
測驗環境:
last_value = 2
生產環境:
last_value = 1
uj5u.com熱心網友回復:
此錯誤意味著在DbContext(背景關系)的生命周期范圍內,該物體已被加載并正在被跟蹤。這可以直接通過不同的方法呼叫,或間接通過作為另一個物體加載的一部分進行急切或延遲加載。Reload將嘗試跟蹤物體,這將導致已跟蹤另一個匹配實體的錯誤。
根據我對您正在嘗試做的事情的了解,您可能不想使用,AsNoTracking()因為您無法保證該物體尚未被跟蹤。按正常方式加載它。
var result = await this.Entities
.OrderByDescending(m => m.Id)
.FirstAsync();
await Context.Entry(result).ReloadAsync();
每當您使用*OrDefault()風味時,您必須處理集合中可能沒有專案的事實。如果您期望至少有一個,請使用First.
這里的缺點是即使已經從資料庫中新加載了所需的專案,也會呼叫 Reload。由于我們不能假設所需的專案已被跟蹤或尚未被跟蹤,因此最好的選擇可能是:
var id = this.Entities
.OrderByDescending(m => m.Id)
.Select(x => x.Id)
.FirstAsync();
var result = this.Entities.Local
.Where(m => m.Id == id)
.SingleOrDefault();
if (result != null)
await Context.Entry(result).ReloadAsync();
else
result = this.Entities
.Where(m => m.Id == id)
.Single();
此代碼在本地跟蹤快取中查找特定專案,如果找到則重新加載它,否則將從資料庫加載當前專案。
這種方法(減去從資料庫中選擇 ID)適用于任何其他情況,即您提前知道您想要什么特定物體,而不是依賴于類似的東西,FirstOrDefault并希望確保任何已經跟蹤的物體可用并重繪 它。
uj5u.com熱心網友回復:
只需檢查以下內容。
- 無論您在做什么
context.Update(或context.Entity.Update(在代碼中的任何地方。(這可能會導致此類問題) - 確保不要持有 DbContext 實體太久。根據 MS 的建議,它們應該是 Transient 或 Scoped(而不是單例)。
如果您context.Update(在代碼中的任何地方執行并持有 DbContext 實體相當長的時間,那么您很可能會在 DbContext 生命周期中多次嘗試更新同一個被跟蹤的物體。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/403728.html
標籤:
