Asp.net-Mvc
為什麼更新父級時實體框架會插入子級?
我在面向 .Net 4.5 的 Windows 服務中有此程式碼,該服務使用數據庫優先的實體框架層:
var existingState = DataProcessor.GetProcessState(workerId); existingState.ProcessStatusTypeId = (int)status; existingState.PercentProgress = percentProgress; existingState.ProgressLog = log; DataProcessor.UpdateProcessState(existingState);與此程式碼在同一解決方案中的數據處理類中:
public ProcessState GetProcessState(int id) { using (var context = new TaskManagerEntities()) { var processes = (from p in context.ProcessStates.Include("ProcessType").Include("ProcessStatusType") where p.IsActive && p.ProcessStateId == id select p); return processes.FirstOrDefault(); } } public ProcessState UpdateProcessState(ProcessState processState) { using (var context = new TaskManagerEntities()) { context.ProcessStates.Add(processState); context.Entry(processState).State = System.Data.EntityState.Modified; context.SaveChanges(); } return processState; }ProcessState 是另外兩個類 ProcessStatusType 和 ProcessType 的父類。當我在 Windows 服務中執行該程式碼時,它會檢索記錄、更新實體並保存它。儘管在上面的程式碼中從未使用過 ProcessType 子項,但當對 ProcessState 實體執行保存時,EF 會在 ProcessType 表上插入並在其中創建一條新記錄。然後它更改 ProcessStatus 實體中的 FK 以將其指向新的子對象並將其保存到數據庫中。
它不會在ProcessStatusType 表中執行此操作,該表設置有基本相同的 FK 父子關係。
我現在有一個數據庫,其中充滿了我不需要的相同 ProcessType 條目,我不知道為什麼會發生這種情況。我覺得我犯了一些我看不到的明顯錯誤,因為這是我的第一個 EF 項目。問題是我允許上下文在呼叫之間過期但保持相同的實體嗎?
使用 Add 會將所有元素的狀態設置為已添加,這會導致插入子元素。當您為此元素指定 EntityState.Modified 時,不會插入父元素。
嘗試在 UpdateProcessState 中使用以下內容,而不是使用 Add。
context.ProcessStates.Attach(processState); context.Entry(processState).State = EntityState.Modified; context.SaveChanges();Attach 會將所有元素的狀態設置為 Unchanged,並通過為父元素指定 Modified 來指示僅應更新此元素。
另一個注意事項。您應該使用強類型
Include(x => x.ProcessType)而不是Include("ProcessType").