EF 6 not selecting recently updated values unless I rebuild the project - c#

In Visual Studio 2012, I have Project#1 that creates and update entries in a SQL DB using EF 6.
And another Project#2 that is supposed to only select the values created/updated from Project #1
Both projects have a connection string to the local DB
Both projects reference a Data access layer library that contains the .edmx file and the generated models.
http://localhost:1535/Project1: Should create or edit an entry on
Payment entity
http://localhost:1896/Project2: Should select values from Payment
entity
The issue is: When I run both applications on different localhost ports I am able to create an entry and select it from the other project
BUT when I want to update an entry I always see the OLD value. And it is only when I rebuild Project #2 in Visual Studio 2012 that I can see the updated value.
Edit action
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Prefix = "paymentform")] PaymentForm paymentform)
{
if (ModelState.IsValid)
{
Payment payment = db.Payments.Find(paymentform.formId);
payment.paymenturl = paymentform.paymenturl;
db.Entry(payment).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(new PaymentConfig());
}
What is happening?

The solution was to avoid using a global variable that initializes the DB context
Here is what I was I doing before in Project#2
public class PayController : Controller
{
Project2Entities db = new Project2Entities();
public ActionResult Index(int? id)
{
//select
}
}
The solution was to simply use using() with the context inside.
public ActionResult Index(int? id)
{
using (var context = new Project2Entities())
{
//select here
}
}
I have no idea why declaring the context as a global variable doesn't work properly. If anyone knows please clarify.

Related

How can I add a database entry using a viewmodel?

I am making a page that will contains several dropdowns and a few textboxes. I have the data being stored in a viewmodel, that is then passed back to my [HttpPost] create method.
I am fairly new to viewmodels, and am wondering how to add a new database entry using data from a viewmodel.
When I go into Debug mode, all my viewmodel entities are populated, but MVC is not making the connection to make a new entry with those values. Current [Post] create method.
[HttpPost]
public ActionResult Create(OrdersViewModel vmobj)
{
if (ModelState.IsValid)
{
order obj = new order();
obj.projectNumber=vmobj.projectID.ToString();
obj.testingPhase = vmobj.testPhaseSt;
obj.unitSerial = vmobj.unitSerialSt;
obj.completeDate = vmobj.completeDate;
obj.closingStatement = vmobj.closingStatement;
db.orders.Add(obj);
return RedirectToAction("Create");
}
return View();
}
You need to call the DbContext.SaveChanges() to apply the changes in the database. Just like Jeroen told you.

How to update just some of properties in Edit action

Preface:
I'm working on a project using MVC 5. We've built up our database from which our model is created. Then, we've added the Controllers and Views using Scaffolding. However in the Views we've omitted some of the properties (they should not be shown to the users).
Problem:
In the actions like Edit, as I hit the save button (to update the model) I encounter an exception and I think it requires me to provide the value of all the properties.
Please let me know how can I update just some of the properties (shown in the view)?
Please note that I need a solution as general as possible, so as to be able to use it in many Edit actions that I have in this project (Indeed this is the hard part).
Code:
The following are some of the codes that I think are most related to this question:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "AreaCode,Tels,Address")] Area area)
{//Area has many more properties (defined as required in the database) and I just need to update
//these : AreaCode,Tels,Address
if (ModelState.IsValid)
{
db.Entry(area).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.Detector = new SelectList(db.Detectors, "DetectorCode", "detectorName", area.Detector);
ViewBag.Grade = new SelectList(db.Grades, "Gradeid", "GradeName", area.Grade);
return View(area);
}
SS:
Answers expressed in a simple way are highly appreciated.
Get your object to update from the database, and sets your model with the old value of properties
public ActionResult Edit([Bind(Include = "AreaCode,Tels,Address")] Area area)
{
YourDbContext _db= new YourDbContext();
Area oldArea = _db.Areas.Where(x => x.ID == area.ID).FirstOrDefault();
// Bind others properties marked with required from database
area.x = oldArea.x;
area.y = oldArea.y;
if (ModelState.IsValid)
{
db.Entry(area).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.Detector = new SelectList(db.Detectors, "DetectorCode", "detectorName", area.Detector);
ViewBag.Grade = new SelectList(db.Grades, "Gradeid", "GradeName", area.Grade);
return View(area);
}

ASP.Net MVC Viewmodels How to map values from a viewmodel to the database tables

I'm trying to use ViewModels and AutoMapper, as I know these are best practice for avoiding lots of issues.
I'm ok using AutoMapper to populate a viewmodel, but I'm not as sure about how to update my database, from the ViewModel being posted back to my controller.
My GET is:
public ActionResult Edit(int id = 0)
{
Customer customer = db.Customers.Find(id);
var offers = db.Offers.Where(x => x.CustomerId == id).ToList();
var email = db.Emails.FirstOrDefault();
var vm = new CreateViewModel();
vm.CustomerId = customer.CustomerId;
vm.ArrivalDate = customer.ArrivalDate;
vm.CustomerName = customer.CustomerName;
vm.EmailAddress = customer.EmailAddress;
vm.NumNights = customer.NumNights;
vm.NumPeople = customer.NumPeople;
vm.EmailBody = email.EmailBody;
vm.From = email.From;
vm.Subject = email.Subject;
// Map list of Offers into ViewModel
vm.Offers = Mapper.Map<IList<Offer>, IList<OfferVM>>(offers);
return View(vm);
}
My POST is:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(EditViewModel vme)
{
if (ModelState.IsValid)
{
// Update the Customer properties
Customer customer = db.Customers.Find(vme.CustomerId);
customer.NumPeople = vme.NumPeople;
customer.NumNights = vme.NumNights;
customer.ArrivalDate = vme.ArrivalDate;
customer.CustomerName = vme.CustomerName;
customer.EmailAddress = vme.EmailAddress;
// Update Offers table
foreach (var o in vme.Offers)
{
// find the offer
Offer offer = db.Offers.Find(o.OfferId);
if (offer != null)
{
// update the properties of Offer
offer.RoomRate = o.RoomRate;
offer.IncludeInOffer = o.IncludeInOffer;
}
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vme);
}
So my Post is manually updating two database tables (Offers and Customers).
The GET method is elegant, using AutoMapper, the POST is not. I'm wondering if there is a more straightforward way of updating the database via AutoMapper, without having to manually go through each property I am looking to update? Or is my POST controller as efficient as it can be?
Thank you for any pointers,
Mark
There is an overload of Map that allows to map properties to one preexisting instance:
Mapper.Map<IObjectA, IObjectB>(objectA, ObjectB);
Thus, you just have to map from the parameter vme (CreateViewModel vme) to the customer recovered from the DB. This also applies to the offers part.
Of course, you'll have to configure the mappings in the reverse direction: you've done it from db objects to view model, and now you need to map them from viewmodel to db objects. If you've followed Automapper conventions it will be pretty easy or even unnnecessary.
EDIT: added interesting comment by Henk Mollema
You can configure AutoMapper to ignore properties, if your ViewModel doesn't contain all the properties from your domain model (which is most likely the case), it won't overwrite them with nulls.
You first need to define your mapping like this:
Mapper.CreateMap<EditViewModel, Customer>();
Your updated action method could look like this. What happens here is your action method receives your view model and checks its validity. If it is valid then it does the mapping from your view model to your domain model. This domain model is then passed to your service or repository layer to update the cusotmer in the database. How you update the record depends entirely on you.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(EditViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}
Customer customer = Mapper.Map<Customer>(viewModel);
customerService.Edit(customer);
return RedirectToAction("List");
}
I hope this can help guide you in the right direction. Your HttpGet action method will work in a similar way.

Entity Framework Update not Working

I wrote my code in ASP.NET MVC 4. I Create a Edit form using MVC edit template and this is my POST code to save edited data.
[AcceptVerbs(HttpVerbs.Post)]
[Authorize(Roles = "User")]
public ActionResult Register(Models.UserBasicProfile profile)
{
if (ModelState.IsValid)
{
using (Models.SocialServicesDataContainer context = new Models.SocialServicesDataContainer())
{
Models.UserBasicProfile update =
context.UserBasicProfiles
.SingleOrDefault(c => c.Id == profile.Id);
if (update.Id > 0)
{
profile.RegisterDate = update.RegisterDate;
update = profile;
context.SaveChanges();
return RedirectToRoute("User_ShowProfile_Alter", new {username = User.Identity.Name });
}
else
{
return View(profile);
}
}
}
This code run correctly and there is no error. But when redirect to user profile occurred, modified fields are still have the previous value.
What should I do ?
Thanks in advance.
I would say it´s because the profile variable is not "connected" to the context. The context is not aware of the profile object. So when running context.SaveChanges() the changes in the profile variable goes unnoticed.
You need to update the update object with the values from profile. Or perhaps attach the profile object to the context.
Check this post on how to attach to the context prior saving Entity Framework 4 - AddObject vs Attach
It looks like you aren't actually changing the data in object returned from the database.
You are setting update = profile, but this just dereferences the update variable so it no longer points at the object being tracked by EF.
You need to copy all the property values from profile to update.

EF4 STE's and MVC2 - ChangeTracker not POSTing

I'm trying to set up an MVC2 app with Entity Framework Self-Tracking-Entities. My view is a strongly-typed view of the entity type generated by the STE T4 template. Here's my GET:
public ActionResult Edit(int id)
{
var ri = new App1Service.App1Client().GetMyObj(id);
var changeTracking = ri.ChangeTracker.ChangeTrackingEnabled; // this shows true
return View(ri);
}
So far, so good. When this form POSTs, however, ChangeTracker is null / reset to default values, and thus, the STE seems suddenly to forget that it's supposed to be tracking itself:
[HttpPost]
public ActionResult Edit(MyObj ri)
{
// MyObj.ChangeTracker.ChangeTrackingEnabled now shows false
// so the following line doesn't save anything:
new App1Service.App1Client().SaveMyObj(ri);
return RedirectToAction("Index");
}
What's the secret to getting the strongly-typed-view to hang onto (and POST back) the whole STE? If I have to go and do another read to get original values and then apply changes, that seems to defeat the purpose of self-tracking-entities, doesn't it?

Categories