this code suppose to update only one value in a table and keep all the other value as is .
how ever I cant find out why , the db.SaveChanges doesn't save it . in the debugger I can see that the value has change ,
this is my code
if (model.rev.GBU == "Good")
{
//This section will do:---- 1> get subjectId -- 2> Update only in the subjectid good rank
//Update this subjectid (int)good +1 data
model.sub.SubjectId = R_getvelue.SubjectId;
//get the relevant value from the Db
var Good = R_getvelue.Good;
int iGoodRating = Convert.ToInt32(Good);
//Add 1 (one )to the value in the Db
iGoodRating++;
model.sub.Good = iGoodRating;
//Keep All the existing data in the other fields
UpdateModel(model.sub);
// db.Entry(model.sub).State = EntityState.Modified; >removing all values biside "Good
}
await db.SaveChangesAsync();
return RedirectToAction("index");
}
ViewBag.OccupationId = new SelectList(db.occupation, "OccupationId", "OccupationDecription", model.Occupation);
return View(model);
}
Related
Can someone help me? I can't update inventory records after purchase, it shows me null error. I can't retrieve the original data from the database.
Here is my code:
DBContext db = new DBContext();
var inTB = db.InventoryTBs.Where(s => s.id == customerTB.CustomerID).FirstOrDefault();
inTB.Quantity += customerTB.CQuantity;
db.InventoryTBs.Add(inTB);
db.SaveChanges();
Thank you
To modify existing record obtained by the context just call SaveChanges():
var inTB = db.InventoryTBs.Where(s => s.id == customerTB.CustomerID).FirstOrDefault();
if (inTB != null)
{
// Modifying existing record
inTB.Quantity += customerTB.CQuantity;
}
else
{
// Adding a new record
db.InventoryTBs.Add(new InventoryTB() { Quantity = customerTB.CQuantity; /* set another properties */});
}
db.SaveChanges();
In your case a record with customerTB.CustomerID does not exist. Therefore, perhaps it's necessary to create new one and then add it to the InventoryTBs.
For additional information see: Modifying data via the DbContext
I am working on a C# method that receives a json object containing the following values.
meetingid
o_agendaitem
o_legistarid
o_title
n_agendaitem
n_legistarid
n_title
The values with an "o" represent the record that comes from the database.
The values with an "n" represent the edited values from a web form.
I put all together to pass it to the C# method:
var data = JSON.stringify({
'meetingid': $scope.meetingId,
'o_agendaitem': o_xref.AgendaItem,
'o_legistarid': o_xref.LegistarID,
'o_title': o_xref.Title,
'n_agendaitem': n_xref.AgendaItem,
'n_legistarid': n_xref.LegistarID,
'n_title': n_xref.Title,
I am having trouble writing the logic in a clear and simple way.
For example, lets say I have the data below:
44841 1 62704 Title#1
44841 2 62218 Title#2
44841 3 62663 Title#3
44841 4 62679 Title#4
44841 5 62709 Title#5
The user edits the values, and changes the 1 for a 6, then the data would change to:
44841 2 62218 Title#2
44841 3 62663 Title#3
44841 4 62679 Title#4
44841 5 62709 Title#5
44841 6 62704 Title#6
Meeting Id and Agenda Item are a Composite Key.
I use the "o" agenda item value and meeting id, to find that record, and if exists, delete it, and then create a new entry with the "n" values.
But I need to check that the meeting id + the "n" agenda item don't exist already too.
Example:
44841 1 62704 Title#1
44841 2 62218 Title#2 < I edit this row, I want to change the 2 for a 6, but I made a mistake and instead entered a 5, then based on my current logic, I would be deleting a record I did not mean to delete. How can I add a new check to make sure that the user is made aware of this error?
44841 3 62663 Title#3
44841 4 62679 Title#4
44841 5 62709 Title#5
This is my attempt to accomplish so far (I added notes in the parts I am not sure if I am doing it right or not):
public ActionResult UpdateXRefItem(Parameters data)
{
bool status = false;
string message = "";
using (Entities entities = new Entities())
{
//use the "o" value to find the record
var oldRec = entities.XRef_WIP.Find(data.meetingId, data.o_agendaItem);
if (oldRec != null) {
//I am not sure if I should remove the record here, or better do a few more checks.
//entities.XRef_WIP.Remove(oldRec);
//use the "n" value combined with the meeting id to see if already exists
var newVal = entities.XRef_WIP.Find(data.meetingId, data.n_agendaItem);
//if the value from the form already exists, return a message to the user
if (newVal != null)
{
status = false;
message = "This Agenda Item already exists for this Cross-Reference List. Please verfy your data and try again.";
}
else{
//after removing the "old" record, and check that the combination of meeting id + agenda item
//do not exist alreay, then create a new table entry.
//I cannot update agenda item because it is part of the composite key.
//entities.XRef_WIP.Add(new XRefWIP
//{
// MeetingID = data.meetingId,
// AgendaItem = data.n_agendaItem,
// LegistarID = data.n_legistarId,
// Title = data.n_title
//});
//status = true;
//message = "Cross-Reference record has been succssfully updated.";
//entities.SaveChanges();
}
}
}
return new JsonResult { Data = new { status = status, message = message } };
}
I hope this makes sens and someone is willing to offer a hand to complete the logic. I think I am close, but I am having trouble putting my ideas together.
Thank you,
Erasmo
See if the solution works, the idea being that you check if the record you want to add exists and if it does you stop the user from proceeding.
public ActionResult UpdateXRefItem(Parameters data)
{
using (Entities entities = new Entities())
{
// First check if the item you are trying to add exists
var currentRec = entities.XRef_WIP.Find(data.meetingId, data.n_agendaItem);
// Stop the user from continueing with the transaction
if (currentRec != null)
return new JsonResult { Data = new { status = false, message = "Record already exists." } };
// Use the "o" value to find the record
var oldRec = entities.XRef_WIP.Find(data.meetingId, data.o_agendaItem);
// If it exists then delete it
if (oldRec != null) {
entities.XRef_WIP.Remove(oldRec);
// Add new record
entities.XRef_WIP.Add(new XRefWIP()
{
MeetingID = data.meetingId,
AgendaItem = data.n_agendaItem,
LegistarID = data.n_legistarId,
Title = data.n_title
});
// Return a new result
return new JsonResult { Data = new { status = true, message = "Success!" } };
}
I have an upload function in my ASP.NET MVC web application which allows a user to upload a document. The system then uses various OCR APIs to read data from the uploaded document, this data is then saved in the "SecondarySchoolSurvey" table in the database. I have a LINQ query in the upload code which finds a row in the database "SecondarySchoolSurvey" table that matches the Id passed in. Various fields in this row are then updated and saved back into the database.
Now this upload function works fine first time. Although if I try to use the upload function again (without restarting the IIS server) then it throws the following error Object reference not set to an instance of an object.
After setting various break points I noticed that the LINQ query: var s1 = db.SecondarySchoolSurveys.FirstOrDefault(s => s.Id == id); returns null the 2nd time it is called i.e. it does not find the record which matches the Id passed in, even though it exists in the database.
So for now, I need to reset the web app IIS server after every time I want to test the upload function. Otherwise this LINQ query with return null the 2nd time I try upload a document. Has anybody seen anything like this before? I'm not sure how useful it will be providing code but here is one of the class, the one which contains the LINQ query:
public class SurveyCheckboxAnswers
{
private RDSContext db = new RDSContext();
//Adds Question 2 answer
public void AddQ2Answer(SurveyCheckboxCollections checkboxes, int id)
{
//find Survey record in db which matches id in order to update with checkbox data
var s1 = db.SecondarySchoolSurveys.FirstOrDefault(s => s.Id == id);
CheckboxData q2Male = checkboxes.SecondarySchoolCheckboxes["Q2Male"];
CheckboxData q2Female = checkboxes.SecondarySchoolCheckboxes["Q2Female"];
CheckboxData q2Other = checkboxes.SecondarySchoolCheckboxes["Q2Other"];
CheckboxData q2DontWantToSay = checkboxes.SecondarySchoolCheckboxes["Q2DontWantToSay"];
//numbers of checkboxes marked for validation
int checkboxValidaiton = 0;
//update SecondarySchoolSurvey checkbox answers in database with IsChecked values from checkbox dictionary
if (q2Male.IsChecked)
{
s1.Q2 = Gender.Male;
checkboxValidaiton++;
}
if (q2Female.IsChecked)
{
s1.Q2 = Gender.Female;
checkboxValidaiton++;
}
if (q2Other.IsChecked)
{
s1.Q2 = Gender.Other;
checkboxValidaiton++;
}
if (q2DontWantToSay.IsChecked)
{
s1.Q2 = Gender.None;
checkboxValidaiton++;
}
//validate only 1 checkbox has been marked
if(checkboxValidaiton == 0)
{
s1.Flag = true;
s1.FlagContent += "| Question2: no checkboxes marked. ";
}
else if (checkboxValidaiton > 1)
{
s1.Flag = true;
s1.FlagContent += "| Question2: more than 1 checkboxes marked. ";
}
db.SaveChanges();
}
//Adds Question 6 answer
public void AddQ6Answer(SurveyCheckboxCollections checkboxes, int id)
{
//find Survey record in db which matches id in order to update with checkbox data
var s1 = db.SecondarySchoolSurveys.FirstOrDefault(s => s.Id == id);
CheckboxData q6Higher = checkboxes.SecondarySchoolCheckboxes["Q6Higher"];
CheckboxData q6Ordinary = checkboxes.SecondarySchoolCheckboxes["Q6Ordinary"];
CheckboxData q6Other = checkboxes.SecondarySchoolCheckboxes["Q6Other"];
//numbers of checkboxes marked for validation
int checkboxValidaiton = 0;
if (q6Higher.IsChecked)
{
s1.Q6a = MathLevel.Higher;
checkboxValidaiton++;
}
if (q6Ordinary.IsChecked)
{
s1.Q6a = MathLevel.Ordinary;
checkboxValidaiton++;
}
if (q6Other.IsChecked)
{
s1.Q6a = MathLevel.Other;
checkboxValidaiton++;
}
//validate only 1 checkbox has been marked
if (checkboxValidaiton == 0)
{
s1.Flag = true;
s1.FlagContent += "| Question6: no checkboxes marked. ";
}
else if (checkboxValidaiton > 1)
{
s1.Flag = true;
s1.FlagContent += "| Question6: more than 1 checkboxes marked. ";
}
db.SaveChanges();
}
//Adds Question 7 answer
public void AddQ7Answer(SurveyCheckboxCollections checkboxes, int id)
{
//find Survey record in db which matches id in order to update with checkbox data
var s1 = db.SecondarySchoolSurveys.FirstOrDefault(s => s.Id == id);
CheckboxData q7Physics = checkboxes.SecondarySchoolCheckboxes["Q7Physics"];
CheckboxData q7Biology = checkboxes.SecondarySchoolCheckboxes["Q7Biology"];
CheckboxData q7Chemistry = checkboxes.SecondarySchoolCheckboxes["Q7Chemistry"];
CheckboxData q7Science = checkboxes.SecondarySchoolCheckboxes["Q7Science"];
CheckboxData q7None = checkboxes.SecondarySchoolCheckboxes["Q7None"];
//numbers of checkboxes marked for validation
int checkboxValidaiton = 0;
if (q7Physics.IsChecked)
{
s1.Q7 = "Physics";
checkboxValidaiton++;
}
if (q7Biology.IsChecked)
{
s1.Q7 += "Biology";
checkboxValidaiton++;
}
if (q7Chemistry.IsChecked)
{
s1.Q7 += "Chemistry";
checkboxValidaiton++;
}
if (q7Science.IsChecked)
{
s1.Q7 += "Science Junior";
checkboxValidaiton++;
}
if (q7None.IsChecked)
{
s1.Q7 += "None";
checkboxValidaiton++;
}
//validate only 1 checkbox has been marked
if (checkboxValidaiton == 0)
{
s1.Flag = true;
s1.FlagContent += "| Question7: no checkboxes marked. ";
}
db.SaveChanges();
}
...
...
...
}
Your problem here most likely lies in the fact you are using a private variable for the db context. The appropriate way to open/close the connection to your db using a context is to use a using statement like so:
using(var db = new RDSContext())
{
//...Do work here with your context
}
Per MSDN
The lifetime of the context begins when the instance is created and ends when the instance is either disposed or garbage-collected. Use using if you want all the resources that the context controls to be disposed at the end of the block. When you use using, the compiler automatically creates a try/finally block and calls dispose in the finally block.
Since your query is running but is returning null, your db context is likely valid. That means the issue is likely the query itself. I suspect that on subsequent runs, you are passing in a different id that has no record in your database. Asking the db for the first record, if any, that matches the supplied id therefor returns null. Use a breakpoint to inspect both the provided id and the generated sql. Check in your db that you have a row for the id.
On another note, I would suggest that you use the method First or Single instead of FisrtOrDefualt if you expect the query to always return a row. This will throw an error if there are no matching rows, which guarantees that you have a not-null result returned if no error is thrown. The advantage is that after the method you now know that there was a matching row, whereas otherwise you may have to include a null check.
There is a great table on these operators here
How can i insert object twice in database with different value
when the object User has Code > 10 then it insert 2 object but some how EF update the value of the first inserted object.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Code { get; set; }
}
and in my action i'm saving to databse
// Post Action
uow.Users.Add(user);
uow.Commit(); // save first time
if (user.Code > 10)
{
user.Name = "NAS";
uow.Users.Add(user);
uow.Commit(); //save second time
}
My object is
User = (Name = "Mike",Code=12)
Database result is
Result Database
id =1 Name="NAS" Code=12
id =2 Name="NAS" Code=12
This is correct behavior; so why is this happening:
When you save the first time, it creates a new entry in the database using your originally created user object.
When you save the second time, it takes the original object, which for lack of a better term, has a database reference and updates the name of the object AND it also adds that same object to the collection again; this is why you are seeing the same information in the database.
Your code should be:
var user = new User { Name = "Mike", Code = 12 };
uow.Users.Add(user);
uow.Commit(); // save first time
if (user.Code > 10)
{
var newUser = new User { Name = "NAS", Code = user.Code };
uow.Users.Add(newUser);
uow.Commit(); //save second time
}
Your results should then be:
Result Database
id = 1 Name = "Mike" Code = 12
id = 2 Name = "NAS" Code = 12
drneel gave a good explanation on why your code does not work as you intended.
Now maybe there is a workaround for what you want to achieve: inserting two distinct entities in DB from a single instance. Detach it from context, change what needs to be changed, re-add it.
If your uow is inheriting from DbContext, it would be:
var user = new User { Name = "Mike", Code = 12 };
uow.Users.Add(user);
uow.Commit(); // save first time
if (user.Code > 10)
{
uow.Entry(user).State = EntityState.Detached;
user.Id = 0;
user.Name = "NAS";
uow.Users.Add(user);
uow.Commit(); //save second time
}
I am not comfortable with the way we have to detach entities in EF. It may work better to instead dispose your uow after first 'save' and use another one for second 'save'.
The main risk concerns navigation properties. Detaching does not ends tracking on collection of other entities which may hold a reference to your user instance. Re-adding it may screw EF navigation properties bookkeeping.
(I would not fear that with NHibernate, such bookkeeping is not handled by NH. It remains the responsibility of the developer with NH.)
I have the following code:
model = new Option();
model.val1 = newVal1;
model.val2 = newVal2;
model.val3 = newVal3;
//this saves new record just fine
if (recordCount < 1)
{
context.Options.AddObject(model);
context.SaveChanges();
}
else
{
var tempID = from s in context.Options where (s.val1 == newVal1 && s.val2 == newVal2) select s.ID;
var resultsID = tempID.First();
model = context.Options.Single(m => m.ID == resultsID);
if (TryUpdateModel(model, new[] { "val3" }))
{
//this isn't updating the record
context.SaveChanges();
}
}
The database adds a new entry just fine, but isn't updating it. What am I missing? Thanks.
Looking at this code, you first make a new model and set some properties on it:
model = new Option(); // <- A
model.val1 = newVal1;
model.val2 = newVal2;
model.val3 = newVal3;
then, assuming you're heading down the "else" path you do this:
var tempID = from s in context.Options where (s.val1 == newVal1 && s.val2 == newVal2) select s.ID;
var resultsID = tempID.First();
model = context.Options.Single(m => m.ID == resultsID); // <- B
if (TryUpdateModel(model, new[] { "val3" }))
{
//this isn't updating the record
context.SaveChanges();
}
which goes out and finds the entry in context.Options that has the matching ID.
So, now that model, which you created via the new() call (which I've marked with the comment "A") is now cast adrift and you've got a different one - the one you retrieved via the call to context.Options.Single(), which I've marked with the comment "B". It has properties based on what's in the context, not what was in that object you made. That A object is gone now. You've got a new object, B, retrieved from the DB.
So now, you're calling TryUpdateModel on this retrieved object, telling it that val3 is updated, but the value hasn't changed, right? It's whatever you pulled from the context.
So, it's not going to update anything because the model object isn't the one you think it is... the one you updated is waiting to be garbage collected. The one you retrieved hasn't been updated because it still has whatever value it's got for the property val3.
Assuming I follow what you're trying to do here, that's why you're not seeing any updated values in the context.
If you want to change the value of the val3 property on that model object you've retrieved, you need to set it after you retrieve it, otherwise it is overwritten.
If you are using a global context, you will have to update the context itself because it is not soft-link to the database.
context.SaveChanges();
DbContext context = new DbContext();
Check if Configuration.AutoDetectChangesEnabled = true;