0

I have landed up in a situation here.

I am loading the User from a custom function here :

public User GetUserById(int Id)
{
    var User = DBContext.Users.SingleOrDefault(x=>x.Id == Id);
    return User;
}

The problem is in the controller where I call this!

var User = GetUserById(Id);
User.Language = UserModel.Language;
//UpdateModel(User); //I tried this but not working.
DBContext.SaveChanges();

The database is not being updated.

I tried loading the User in the controller directly with linq and things go fine.

But, Why is it not working the other way?

Is there any workaround to make it work with this function?

Isn't there any function like DBContext.Users.Update(User). I remember using something similar, but am not able to recollect!

4
  • DBContext is a class of what? Commented May 15, 2017 at 15:40
  • @casillas it'a a class that derives from DbContext class. It contains the DbSet<User> Users Commented May 15, 2017 at 15:48
  • @PrashanthBenny Do the DBContext in the GetUserById and the DBContext in your controller refer to the same instance? Or are they different instances? If they're different instances, then it shouldn't work because they have different change trackers. Commented May 15, 2017 at 18:47
  • @EBrown Yes, I have put GetUserById as a method in the UserService which is in the services namespace. and The place where I'm trying to update is UsersController. Commented May 15, 2017 at 19:11

1 Answer 1

2

As EBrown said, they need to be the same instance of DbContext. I'm betting your service uses one context and the controller another. So now when it gets to the controller it is disconnected and not tracked by EF.

The solution is to reconnect it to the context used by the controller (there are other ways to achieve this as well).

var User = GetUserById(Id);  // returns a disconnected user
User.Language = UserModel.Language;

// Attach back to context and tell EF it is updated
DBContext.Users.Attach(User);
DBContext.Entity(User).State=EntityState.Modified;

DBContext.SaveChanges();

If this is your postback code, you could just as well write aUserUpdate function:

public void UpdateUser(UserModel userViewModel)
{
    var userEntity = DBContext.Users.Find(userViewModel.Id);  // Get your user from database
    Mapper.Map(userViewModel, userEntity);  // Use Automapper to move the changed fields into your entity
    DbContext.SaveChanges();
}

Then your controller POST is simply:

if (ModelState.IsValid)
{
    UpdateUser(UserModel);
    // redirect to list or where ever...
}
Sign up to request clarification or add additional context in comments.

2 Comments

So, I need to either attach my entity returned by the function to the one in the Controller or write another function for update with automapper.
The key concept to know is how entity framework tracks entities. When you fetch it from the context it is automatically tracked for the lifetime of that context. Once the context is gone, it is no longer tracked by the next instance, so you need to add it back to tracking. The update function is just an example of the ViewModel pattern many use. Fetch the entity, move the changes from your view model back to the entity and save. Automapper is not required but saves a lot of work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.