![](/img/trans.png)
[英]Saving AutoMapper mapped Collections of Entities using Entity Framework
[英]Use AsNoTracking for entities mapped from AutoMapper
我有一種情況,我正在使用自動映射器映射DTO->數據庫實體。
var entityObj = _mapper.Map<REQUESTEXT>(reqDTO);
然后,我正在使用entityObj
更新數據庫中的記錄。
void Update(REQUESTEXT entityObj)
{
_context.REQUESTEXTs.Attach(entityObj); <--- Error
_context.Entry(entityObj).Property(x => x.CUSTOPTIONCD).IsModified = true;
_context.SaveChanges();
}
當我嘗試將REQUESTEXT
對象附加到上下文時,它給我一個錯誤:
附加類型“ A”的實體失敗,因為相同類型的另一個實體已經具有相同的主鍵值。 如果圖形中的任何實體具有相互沖突的鍵值,則使用“附加”方法或將實體的狀態設置為“不變”或“修改”時,可能會發生這種情況。 這可能是因為某些實體是新實體,尚未收到數據庫生成的鍵值。 在這種情況下,請使用“添加”方法或“已添加”實體狀態來跟蹤圖形,然后根據需要將非新實體的狀態設置為“未更改”或“已修改”。
按照這個SO答案: https : AsNoTracking()
我需要使用AsNoTracking()
,我不確定如何在AutoMapper
使用它嗎?
有什么建議么?
AsNoTracking指的是何時由上下文而不是由Automapper加載實體。 之所以會收到錯誤,是因為在DbContext生命的某個時刻,它已使用該ID加載了實體並正在對其進行跟蹤。 他們建議的選項是將您的實體加載切換為使用AsNoTracking,這可以有效地告訴EF在讀取實體時不要跟蹤該實體。
解決該問題的另一種方法是先檢查DbContext的本地緩存中是否存在該實體,如果找到該實體,則使用AutoMapper將屬性更改映射到該現有實體,而不是創建一個新實體。
例如:
var existingEntity = _context.REQUESTEXTs.Local.SingleOrDefault(x => x.EntityId == reqDTO.EntityId);
if(existingEntity != null)
mapper.Map(reqDto, existingEntity);
else
{
var entityObj = _mapper.Map<REQUESTEXT>(reqDTO);
_context.REQUESTEXTs.Attach(entityObj);
_context.Entry(entityObj).Property(x => x.CUSTOPTIONCD).IsModified = true;
}
_context.SaveChanges();
這將檢查現有實體的本地緩存(不命中數據庫),如果找到,則使用AutoMapper更新其屬性。 實體跟蹤將記錄這些更改,因此,在調用SaveChanges時,修改將進入數據庫。 如果本地緩存中沒有該實體,那么我們將創建一個新實例,將其附加,將其標記為已修改,然后保存。
您的示例中似乎缺少一個建議:您應該驗證以下假設:
如果這是一個Web應用程序/帶有可訪問的Controller動作或Web API端點,則可以利用此漏洞允許用戶編輯原本不應該的記錄,或者以不應該的方式更新記錄。 (不要從客戶端請求中獲得任何信任。)每個請求都應經過徹底驗證,並且檢測到的任何偏差都應終止客戶端會話。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.