user我在和之間有一個多對多的關系project。像:
class User
{
public ICollection<Project> Projects { get; set; }
}
class Project
{
public ICollection<User> Users { get; set; }
}
Entity Framework 自動生成中間表。
問題是我想更新用戶以及整個專案串列。此串列可能已被以任何方式修改,專案可能已被添加和洗掉。同時在用戶物件被更新之前。
我總是得到同樣的錯誤,物體框架試圖在中間表中添加一個重復的條目。
我嘗試了很多沒有成功的事情(下面列出了一些)。
var tmp = Context.Entry(user); // user being the updated object.
tmp.State = EntityState.Modified;
tmp.Collection(e => e.Projects).IsModified = true;
Context.Users.Update(user);
Context.SaveChanges();
或者
var tmp = Context.Users.SingleOrDefault(u => u.Id == user.Id);
if (tmp == null)
return null;
Context.Entry(tmp).CurrentValues.SetValues(user);
Context.SaveChanges();
return user;
或者只是簡單的舊更新:
Context.Users.Update(user);
Context.SaveChanges();
但這些都不起作用。
uj5u.com熱心網友回復:
這個問題聽起來像你有一個帶有一組專案的分離用戶物體,你想將它傳遞給一個方法,與 DbContext 關聯以保持更改。
您遇到了加倍記錄的問題,因為當您將用戶附加到 DbContext 時,它會將與用戶關聯的每個 Project 物體視為新實體,因為它們本身不參考跟蹤的實體。
使用關聯更新分離的物體是相當復雜的,尤其是在您希望在操作中添加或洗掉關聯的情況下。
推薦的方法是從資料庫加載當前用戶和專案,然后利用 Automapper 來保護您可以從分離物體復制哪些值,然后通過關聯添加/洗掉任何已更改的專案參考。如果可以創建一個全新的專案以作為此操作的一部分與用戶關聯,那么您也需要處理它。
var existingUser = Context.Users.Include(x => x.Projects).Single(x => x.UserId == user.UserId);
Mapper.Map(user, existingUser);
// Where Automapper is configured with a User to User mapping with allowed
// values to copy over, ignoring anything that cannot legally be changed.
var newProjectIds = user.Projects.Select(x => x.ProjectId).ToList();
var existingProjectIds = existingUser.Projects.Select(x => x.ProjectId).ToList();
var projectIdsToAdd = newProjectIds.Except(existingProjectIds).ToList();
var projectIdsToRemove = existingProjectIds.Except(newProjectIds).ToList();
var projectsToAdd = Context.Projects.Where(x => projectIdsToAdd.Contains(x.ProjectId)).ToList();
var projectsToRemove = existingUser.Projects.Where(x => projectIdsToRemove.Contains(x.ProjectId)).ToList();
foreach(var project in projectsToRemove)
existigUser.Projects.Remove(project);
foreach(var project in projectsToAdd)
existingUser.Projects.Add(project);
Context.SaveChanges();
...這個例子不包括全新專案的可能性。如果更新后的用戶可以包含一個全新的專案,那么您需要在查找 projectsToAdd 時檢測這些專案以從傳入的專案串列中添加 ID 位于新專案 ID 中但在資料庫中未找到的任何專案。這些分離的參考可以添加到從 DbContext 加載的用戶中,但是您確實需要處理每個專案可能必須避免重復的任何導航屬性,用對跟蹤物體的參考替換每個導航屬性,包括回傳的任何雙向參考用戶(如果存在)。
通常,處理分離的物體有各種考慮因素,您需要牢記并謹慎處理。通常最好避免傳遞分離的物體,而是旨在傳遞您想要關聯的資料的最小表示,然后加載和調整該服務器端。通常使用分離物體的理由是避免再次加載資料,但是這會在嘗試同步這些分離實體時導致更多代碼,并且忽略了資料狀態可能在分離實體被采用后發生變化的事實。例如,上面的代碼還應該查看分離物體和加載狀態之間的物體版本,以檢測是否有其他人可能進行了更改,因為在用戶行程開始時讀取了分離副本以進行更改。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/459593.html
