I'm practicing MVC 5 and in my application I have a controller method that should update address info for a given user profile.
I do this by accessing the database with a context object, and my first thought was to copy the database row to an object, make the changes and then put it back using the AddOrUpdate()
method. However, I only see an Add()
method.
So instead I did the following:
public ActionResult EditBillingDetails(EditBillingDetailsViewModel model)
{
if (ModelState.IsValid)
{
string id = User.Identity.GetUserId();
ApplicationDbContext db = new ApplicationDbContext();
db.Users.Single(u => u.Id == id).FirstName = model.FirstName;
db.Users.Single(u => u.Id == id).LastName = model.LastName;
db.Users.Single(u => u.Id == id).Email = model.Email;
db.Users.Single(u => u.Id == id).Address = model.Address;
db.Users.Single(u => u.Id == id).City = model.City;
db.Users.Single(u => u.Id == id).ZIP = model.ZIP;
db.Users.Single(u => u.Id == id).Country = model.Country;
db.SaveChanges();
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangeBillingSuccess });
}
return View(model);
}
Which works just fine, but it feels wrong to go look up the same entry 7 times just to update each field one by one. Isn't there a better way to do this?
The db.SaveChanges()
will take care of updating an entity with new values if you retrieved it from the database. EF "tracks" entities that you query from the database (in this instance, the call to .Single()
) and knows to persist changes back to the databse if you alter any properties of that entity. You only have to Add
to the database if you are creating a completely new entity.
var user = db.Users.Single(u => u.Id == id);
user.FirstName = model.FirstName;
user.LastName = model.LastName;
user.Email = model.Email;
user.Address = model.Address;
user.City = model.City;
user.ZIP = model.ZIP;
user.Country = model.Country;
db.SaveChanges();
Assuming this is Entity-Framekwork and you haven't changed any default configurations (caching), your code, although very specific, only the first Single()
will make the database call to retrieve the object. So functionally it would be the same as:
var user = db.Users.Single(u => u.Id == id);
user.FirstName = model.FirstName;
user.LastName = model.LastName;
user.Email = model.Email;
user.Address = model.Address;
user.City = model.City;
user.ZIP = model.ZIP;
user.Country = model.Country;
db.SaveChanges();
There may be a additional (so minor) code execution depending on if the compiler would change your code in IL to the code I wrote.
Why not get the user from the context?
public User GetUser(int id)
{
DbContext context = new YourDbContext();
return context.Users.Find(id);
}
public void SaveUser(User user)
{
DbContext context = new YourDbContext();
context.Entry(user).State = EntityState.Modified;
context.SaveChanges();
return;
}
In your Controller, you would update the User's properties and save it:
DbContext context = new YourDbContext();
User user = GetUser(User.Identity.GetUserId());
user.Value1 = model.Value1;
user.Value2 = model.Value2;
SaveUser(user);
return RedirectToAction(...);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With