我正在尝试找到一种方法,允许我更新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编辑方法
[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 :(得分:0)
不是在控制器中创建新的UserProfile
,而是从存储库中获取UserProfile
,修改其字段,然后将其发送回UpdateUserProfile
并致电Save
。
答案 1 :(得分: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);
}
}