2013-06-06 65 views
0

我試圖找到一種方法,允許我更新UserProfile實體以及用戶分配給的角色列表。我已經寫了下面的代碼,但它不起作用。使用實體框架更新UserProfile及其角色

public void UpdateUserProfile(UserProfile userProfile) 
{ 
    context.Entry(userProfile).State = EntityState.Added; 

    var databaseRoleIds = context.Roles 
    .Where(r => r.UserProfiles 
     .Any(u => u.UserId == userProfile.UserId)) 
     .Select(r => r.RoleId).ToList(); 

    var clientRoleIds = userProfile.Roles.Select(r => r.RoleId).ToList(); 

    var removedRoleIds = databaseRoleIds.Except(clientRoleIds).ToList(); 

    var addedRoleIds = clientRoleIds.Except(databaseRoleIds).ToList(); 

    var unchangedRoleIds = removedRoleIds.Union(addedRoleIds).ToList(); 

    foreach (var roleId in unchangedRoleIds) 
    { 
    var role = context.Roles.Find(roleId); 
    context.Entry(role).State = EntityState.Unchanged; 
    } 

    foreach (var roleId in removedRoleIds) 
    { 
    userProfile.RemoveRole(context.Roles.Find(roleId)); 
    } 

    foreach (var roleId in addedRoleIds) 
    { 
    userProfile.AddRole(context.Roles.Find(roleId)); 
    } 

    context.Entry(userProfile).State = EntityState.Modified; 

} 

這裏是的UnitOfWork

namespace MvcWebsite.WorkUnits 
{ 
public class WorkUnit : IWorkUnit, IDisposable 
{ 
private MvcContext context = new MvcContext(); 
private RoleRepository roleRepository; 
private UserProfileRepository userProfileRepository; 

public IRoleRepository RoleRepository 
{ 
    get 
    { 
    if (this.roleRepository == null) 
    { 
     roleRepository = new RoleRepository(context); 
    } 
    return roleRepository; 
    } 
} 

public IUserProfileRepository UserProfileRepository 
{ 
    get 
    { 
    if (this.userProfileRepository == null) 
    { 
     userProfileRepository = new UserProfileRepository(context); 
    } 
    return userProfileRepository; 
    } 
} 

public void Save() 
{ 
    context.SaveChanges(); 
} 

private bool disposed = false; 

protected virtual void Dispose(bool disposing) 
{ 
    if (!this.disposed) 
    { 
    if (disposing) 
    { 
     context.Dispose(); 
    } 
    } 
    this.disposed = true; 
} 

public void Dispose() 
{ 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 

} 
} 

...這裏是HttpPost Edit方法

[HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Edit(UserProfileEditViewModel model) 
    { 
     try 
     { 
     if (ModelState.IsValid) 
     { 
      var clientUserProfile = new UserProfile(); 
      clientUserProfile.UserId = model.UserId; 
      clientUserProfile.UserName = model.UserName; 
      clientUserProfile.FirstName = model.FirstName; 
      clientUserProfile.LastName = model.LastName; 
      clientUserProfile.Email = model.Email; 
      clientUserProfile.RowVersion = model.RowVersion; 
      clientUserProfile.Roles = new List<Role>(); 
      foreach(var role in model.Roles) 
      { 
      if (role.Assigned) 
      { 
       clientUserProfile.Roles.Add(new Role 
       { 
       RoleId = role.RoleId, 
       RoleName = role.RoleName, 
       RowVersion = role.RowVersion, 
       }); 
      } 

      } 
      unitOfWork.UserProfileRepository.UpdateUserProfile(clientUserProfile); 
      unitOfWork.Save(); 
      return RedirectToAction("Details", new { id = clientUserProfile.UserId }); 

     } 
     } 
     catch (DataException ex) 
     { 
     ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator."); 
     } 
     return View(model); 
    } 

有沒有人有這是爲什麼不工作的任何想法?或者可以在實際工作的地方建議一個教程。任何幫助,一如既往,非常感謝。

+0

你周圍改變實體狀態刪除,但你不打電話'的SaveChanges()'。你是否在功能之外這麼做? – bcr

+0

是的,我已經使用了UnitOfWork模式,所以這是來自UnitOfWork.UserProfileRepository.UpdateUserProfile的方法。這個UnitOfWork包含一個傳遞給每個使用的倉庫的上下文,然後在該上下文中調用SaveChanges。我編輯了上面的代碼來顯示控制器方法。 – MickySmig

回答

0

而是在你的控制器創建一個新的UserProfile的,請從庫中UserProfile,修改它的字段,然後將其發送回UpdateUserProfile並調用Save

+0

這就是我最初想到的,但如果另一個用戶在此期間更新,那將改變RowVersion的OriginalValue。實體框架在比較實體以評估是否發生併發衝突時使用(只讀)OriginalValues – MickySmig

+0

看來您面臨兩個不同的問題:1)更新實體和2)併發策略。 – Jasen

0

終於發現我把它完全弄錯了。我根本沒有改變關係。我已經包含下面的代碼,這讓我附上父實體修改,然後標記的關係,因爲添加的,並根據需要

public void UpdateUserProfile(UserProfile userProfile) 
{ 
    context.Entry(userProfile).State = EntityState.Modified; 
    var objectContext = ((IObjectContextAdapter)context).ObjectContext; 

    foreach (var role in userProfile.Roles) 
    { 
    context.Entry(role).State = EntityState.Unchanged; 
    } 

    var databaseRoleIds = context.Roles 
    .Where(r => r.UserProfiles 
     .Any(u => u.UserId == userProfile.UserId)) 
     .Select(r => r.RoleId) 
     .ToList(); 

    var clientRoleIds = userProfile.Roles.Select(r => r.RoleId).ToList(); 

    var removedRoleIds = databaseRoleIds.Except(clientRoleIds).ToList(); 

    var addedRoleIds = clientRoleIds.Except(databaseRoleIds).ToList(); 

    foreach (var roleId in removedRoleIds) 
    { 
    var role = context.Roles.Find(roleId); 
    objectContext 
     .ObjectStateManager 
     .ChangeRelationshipState(userProfile, role, u => u.Roles, EntityState.Deleted); 
    } 

    foreach (var roleId in addedRoleIds) 
    { 
    var role = context.Roles.Find(roleId); 
    objectContext 
     .ObjectStateManager 
     .ChangeRelationshipState(userProfile, role, u => u.Roles, EntityState.Added); 
    } 
}