0

I'm trying to update my existing ApplicationUser, by adding new "non-core" properties e.g. FirstName, LastName. I've extented these properties already via ApplicationUser: IdentityUser, this works overall fine.

Now, what I try to do is create a new ApplicationUser in my controller, and then pass it to repository to update user existing in db, like:

public ActionResult Members_Update(MemberViewModel mvm){
    ApplicationUser user = new ApplicationUser();
    user.FirstName = mvm.FirstName;
    user.LastName = mvm.LastName;
    _repo.UpdateApplicationUser(user);
}

In repository ( constructed as _context = new ApplicationDbContext(); ) I do:

public void UpdateAppicationUser(ApplicationUser updatedUser){
    _context.Users.Attach(updatedUser);
    var entry = _context.Entry(updatedUser);
  ...

and then I continue via

entry.Property(x => x.AccessFailedCount).IsModified = false;
entry.Property(x => x.EmailConfirmed).IsModified = false;
entry.Property(x => x.LockoutEnabled).IsModified = false;
// same for rest of core identity properties
_context.SaveChanges();
}

I'm trying to do this based on this pattern, so that the db is only hit once (and overall looks like an optimal way), however there seems to be some Identity behaviour preventing this. After Attach the entry is just replacing the original user instead of modifying (so e.g. UserName ends up being null, which is naturally required).

Community
  • 1
  • 1
Turo
  • 1,537
  • 2
  • 21
  • 42
  • You have to set old values before the call to Attach, en new values after that call. – Kris Vandermotten Sep 20 '16 at 13:56
  • that's not the case, because updatedUser entry does not belong to context until it is attached. Your approach throws Member 'isModified' cannot be called for propeerty x.. because the entity of type 'ApplicationUser' does not exist in the context. – Turo Sep 20 '16 at 14:04
  • sorry modified my comment slightly as it was awkward not precise terminology, hope it's better now – Turo Sep 20 '16 at 14:06
  • Try `Add` instead of `Attach`, set `State` to `Unchanged`,continue as you do now and check if it works for you. Something like `context.Users.Add(updatedUser); var entry = _context.Entry(updatedUser); enty.State = EntityState.Unchanged; entry.Property(x => x.AccessFailedCount).IsModified = false; entry.Property(x => x.FirstName).IsModified = true; ..... _context.SaveChanges();` – Adil Mammadov Sep 20 '16 at 14:08
  • This does not work either, similar as initial approach. However interestingly I wonder how Add would even be possible, as it is supposed to create new entity. Suprisingly it does not throw any errors at initial stage when I try to add new ApplicationUser with the same ID which already belongs to db. – Turo Sep 20 '16 at 14:36
  • Again, your current code sets the new values for the properties you want to update before the call to attach. You have to do that after the call to attach. Likewise, the identifying properties have to be set before attaching. If that is not possible, you may have to set IsModified to correct values for each property, but I'm not familiar with that technique. Note: when I say "set the value of a property" I mean just that, not "set the value of IsModified for that propery" (which is how you seem to have interpreted my previous comment) – Kris Vandermotten Sep 20 '16 at 14:47
  • Hi Kris, an example would speak a thousand words, I'm not quite sure what you mean. Currently I managed to achieve what I need, just with 2 db calls. I think I will need to change the design anyways, I thought I would learn about some ideal approach, but it seems Identity makes it more difficult - the approach I use seems to be very optimal for regular entities (I should likely check this as well). – Turo Sep 20 '16 at 15:10

0 Answers0