我是 C# 和 .NET 核心的新手。
我想知道為什么在使用系結編輯模型時,它會創建一個新模型并系結帖子中的屬性。但是,如果您不將所有欄位放在表單帖子中作為隱藏和系結,它將使它們無效?
難道它不應該加載一個模型并更新系結引數而不管這些引數嗎?
例如,如果我正在更新一個人,而這個人有
Id, Name, Age, updated, Created
Edit(int id, [Bind("Id,Name,Age") Person p]
當我去 時_context.update(p),它被抵消了updated,Created因為它們沒有被系結。
為什么它會這樣作業?
我怎樣才能讓它只更新系結引數而不清除我不需要加載的引數?
uj5u.com熱心網友回復:
您傳入的是 MVC 映射到物體定義的反序列化資料塊。它不會自動神奇地打開 DbContext、加載物體和覆寫值,它只是創建物體的一個實體,并在其中復制值。其他所有內容都將保留為默認值。
作為一般規則,我建議不要將物體從客戶端傳遞到服務器,以避免混淆發送回的內容。執行更新時,接受具有要更新的適用屬性的視圖模型,理想情況下,資料模型和視圖模型應包含行版本號。(即 SQL Server 中的 Timestamp 列可以與 Base64 字串相互轉換以在 ViewModel 中發送/比較)
從那里,當執行更新時,您通過 ID 獲取物體,比較時間戳,然后可以利用 Automapper 處理將資料從 ViewModel 復制到物體,或手動復制值。
這樣,當您的 ViewModel 回傳要更新的資料時:
using (var context = new AppDbContext())
{
var entity = context.Persons.Single(x => x.Id == id);
if (entity.TimeStampBase64 != viewModel.TimestampBase64)
{
// Handle fact that data has changed since the client last loaded it.
}
Mapper.Map(entity, viewModel);
context.SaveChanges();
}
您可以按原樣使用物體定義并仍然加載現有物體并使用 Automapper 將值從傳輸物體類復制到 DbContext 跟蹤的物體類,但是最好避免在跟蹤的“真實”物體實體之間混淆物體實體,并且可能不完整的未跟蹤過境實體。代碼通常具有接受物體作為引數來執行驗證、計算等操作的方法,如果稍后這些方法假設它們將獲得“真實”物體,而不是在僅具有瞬態 DTO 風味的某個地方被呼叫,則可能會令人困惑一個物體。
將物體放入并呼叫它似乎更簡單DbContext.Update(entity),但這會給您帶來許多問題,包括:
- 您需要將有關物體的所有資訊傳遞給客戶端,以便客戶端可以將其發送回服務器。這需要隱藏輸入或序列化頁面中的整個物體,向瀏覽器公開更多關于您的域模型的資訊。這增加了客戶端和回傳的有效負載大小。
- 由于您需要序列化所有內容,“快速修復”(例如將
<script>塊中的整個物體序列化以供以后使用)可能會導致延遲加載“意外”,因為序列化程式將嘗試觸及所有導航屬性。 - 將物體傳遞回服務器以執行
Update()信任從客戶端回傳的資料的手段。瀏覽器除錯工具可以攔截表單提交或 Ajax POST 并篡改有效負載中的資料。這可以為意外篡改打開大門。DbContext.Update也會導致 UPDATE 陳述句覆寫所有列,無論是否發生任何更改,其中更改跟蹤物體將僅構建 UPDATE 陳述句以包含僅在任何實際更改時實際更改的值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/313337.html
