MVC4 Entity Framework one paticular column not updating - c#

I am having an infuriating issue where one paticular column in my entity will not save/update. I have tried numerous methods of updating the row such as manally assigning each property I want to update, to where I am now (see code block below). 2 columns update and save as expected (absent_type_id, and point_value) however no matter what I do the "description" column just will not save.
I have checked the debugger to see what the value is before the db.SaveChanges(); and confirmed it is set to the new value; however, selecting the row after the save (and checking the database) shows that the others values are updated, but the description reverts back to what it was...why could this be?
[HttpPost]
public JsonResult UpdateOccurrence(int occ_id,
string absent_type,
string description,
int point_value)
{
try
{
// Get id for the absent type
int absent_type_id = db.AT_absent_types.Single(a => a.absent_type == absent_type).absent_type_id;
var occurrenceToUpdate = new AT_occurrences
{
occ_id = occ_id,
absent_type_id = absent_type_id,
description = description,
point_value = point_value
};
db.AT_occurrences.Attach(occurrenceToUpdate);
db.SaveChanges();
//return call omitted
}
catch (Exception ex)
{
return Json(new {Result = "ERROR", Message = ex.Message});
}
}
As I mentioned - posting the point_value and absent_type save and update the entity perfectly, the description just will not save! i have no idea why. Any help or insight would be very much appreciated - this is driving me crazy! Cheers!

This may not be the answer you're looking for, but whenever I face a similar issue with EF, I delete the table completely, then build. If you're using TFS, you can always undo your pending changes if this doesn't work, which is the caveat I use when I do this for myself.

You use "Attach" to attach a disconnected property to the context. My understanding is Entity Framework has no way of knowing that the properties you're changing are different from those in the DB. So you have to explicitly tell the EF that you've changed a property.
Like this:
db.Entry(occurenceToUpdate).Property(o=>o.occ_id).IsModified = true;
or like this:
db.Entry(occurenceToUpdate).Property("occ_id").IsModified = true;
You'll have to repeat it for each properties you're setting.
I know for sure the above works but you can also try the following. If you're setting all the properties of the entity object, check if something like this works:
db.Entry(occurenceToUpdate).State = EntityState.Modified.

Related

ASP.NET C#: Entity updating is being blocked

Experiencing an issue about updating mysql DB through EF. It's not the first time I'm dealing with it, so I had some ideas about why isn't my data getting changed. I tried changing an element in goods array; tried editing an object, recieved through LINQ-request (seen some examples of this method); made some attempts on marking element found in the database before editing (like EntityState and Attach()). Nothing of these made any difference, so I tried removing <asp:UpdatePanel> from Site.Master to see what happens (responsive for postback blocking to prevent page shaking on update), but nothing changed (while btnRedeemEdit.IsPostBack having its default value).
Code below is the function I use for updates.
protected void btnRedeemEdit_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString["id"]))
{
var db = new GoodContext();
var goods = db.Goods.ToList();
Good theGood = goods.FirstOrDefault(x => x.Id == int.Parse(Request.QueryString["id"]));
//db.Goods.Attach(theGood);//No effect
//db.Entry(theGood).State = System.Data.Entity.EntityState.Modified; //No effect
if (theGood != default)
{
theGood.AmountSold = GetInput().AmountSold;
theGood.APF = GetInput().APF;
theGood.Barcode = GetInput().Barcode;
theGood.Description = GetInput().Description;
theGood.ImagesUrl = GetInput().ImagesUrl;//"https://i.pinimg.com/564x/2d/b7/d8/2db7d8c53b818ce838ad8bf6a4768c71.jpg";
theGood.Name = GetInput().Name;
theGood.OrderPrice = GetInput().OrderPrice;
theGood.Profit = GetInput().Profit;
theGood.RecievedOn = GetInput().RecievedOn;//DateTime.Parse(GetInput().RecievedOn).Date.ToString();
theGood.TotalAmount = GetInput().TotalAmount;
theGood.WeightKg = GetInput().WeightKg;
//SetGoodValues(goods[editIndex],GetInput());//Non-working
db.SaveChanges();
Response.Redirect("/AdminGoods");
}
else Response.Write($"<script>alert('Good on ID does not exist');</script>");
}
else Response.Write($"<script>alert('Unable to change: element selected does not exist');</script>");
}
Notice, that no alerts appear during execution, so object in database can be found.
Are there any more things, that can be responsible for blocking database updates?
A few things to update & check:
Firstly, DbContexts should always be disposed, so in your case wrap the DbContext inside a using statement:
using (var db = new GoodContext())
{
// ...
}
Next, there is no need to load all goods from the DbContext, just use Linq to retrieve the one you want to update:
using (var db = new GoodContext())
{
Good theGood = db.Goods.SingleOrDefault(x => x.Id == int.Parse(Request.QueryString["id"]));
if (theGood is null)
{
Response.Write($"<script>alert('Good on ID does not exist');</script>");
return;
}
}
The plausible suspect is what does "GetInput()" actually do, and have you confirmed that it actually has the changes you want? If GetInput is a method that returns an object containing your changes then it only needs to be called once rather than each time you set a property:
(Inside the using() {} scope...)
var input = GetInput();
theGood.AmountSold = input.AmountSold;
theGood.APF = input.APF;
theGood.Barcode = input.Barcode;
theGood.Description = input.Description;
// ...
db.SaveChanges();
If input has updated values but after calling SaveChanges you aren't seeing updated values in the database then there are two things to check.
1) Check that the database connection string at runtime matches the database that you are checking against. The easiest way to do that is to get the connection string from the DbContext instance's Database.
EF 6:
using (var db = new GoodContext())
{
var connectionString = db.Database.Connection.ConnectionString; // Breakpoint here and inspect.
EF Core: (5/6)
using (var db = new GoodContext())
{
var connectionString = db.Database.GetConnectionString();
Often at runtime the DbContext will be initialized with a connection string from a web.config / .exe.config file that you don't expect so you're checking one database expecting changes while the application is using a different database / server. (More common than you'd expect:)
2) Check that you aren't disabling tracking proxies. By default EF will enable change tracking which is how it knows if/when data has changed for SaveChanges to generate SQL statements. Sometimes developers will encounter performance issues and start looking for ways to speed up EF including disabling change tracking on the DbContext. (A fine option for read-only systems, but a pain for read-write)
EF6 & EF Core: (DbContext initialization)
Configuration.AutoDetectChangesEnabled = false; // If you have this set to false consider removing it.
If you must disable change tracking then you have to explicitly set the EntityState of the entity to Modified before calling SaveChanges():
db.Entry(theGood).State = EntityState.Modified;
db.SaveChanges();
Using change tracking is preferable to using EntityState because with change tracking EF will only generate an UPDATE statement if any values have changed, and only for the values that changed. With EntityState.Modified EF will always generate an UPDATE statement for all non-key fields regardless if any of them had actually changed or not.

context.Entry(original).CurrentValues.SetValues(model); not setting values

I am working with .Net Core and EF Core and have an issue where context.Entry(original).CurrentValues.SetValues(model); is not setting the values.
Some items in original are null, where they are not null in the model and I would have expected that they would be updated.
I also have string values that are not being set too.
There is no error either.
When stepping through the code, there is nothing to suggest that things are going wrong.
If I were to do
Original.Competencies = model.competencies and then context.SaveChangesAsync() this works.
this is the code block in its totality.
using (var context = GetDbContext())
{
var model = reportLesson.Adapt<RepositoryReportLesson>();
var original = context.ReportLessons.Find(reportLesson.Id);
context.Entry(original).CurrentValues.SetValues(model);
context.Entry(original).State = EntityState.Modified;
await context.SaveChangesAsync();
_logger.LogInformation($"->> Updated report lesson id: {id}");
return context.Entry(model).Entity.Adapt<ReportLessonLogicModel>();
}
So the question is, what is causing this to not set the values, and how do I get around it?

DbUpdateConcurrencyException: Entities may have been modified or deleted since entities were loaded

i´m using EF6.
After i clear a tabel and i want to add a new entry to that table i get the following error:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded
The code for deleting the databasetable:
public void ResetStatistics() {
_lisDatabase.Database.ExecuteSqlCommand("TRUNCATE TABLE Sortedtubes");
_lisDatabase.sortedtubes.Local.Clear();
}
After that i want to add a new entry to that table with the following code:
Sortedtubes tube = new Sortedtubes();
tube.Time = time;
tube.Milliseconds = time.Millisecond.ToString();
tube.Barcode = barcode;
tube.Tubetype = tubeType;
tube.Target = target;
tube.Materialcode = materialCode;
try {
_lisDatabase.sortedtubes.Add(tube);
_lisDatabase.SaveChanges(); // Error appears here
} catch (DbUpdateConcurrencyException ex) {
// maybe do something here?
}
I tryed the sugestions on the EF documentation with no luck:
https://msdn.microsoft.com/en-us/data/jj592904
EDIT
The problem seems to be the Clear() method (_lisDatabase.sortedtubes.Local.Clear();). After i execute this method the error appears after the next SaveChanges().
So maybe there is an other way to handle this? I have a GridView in my application witch is bind to the sortedtubes entity and i clear it so that the GridView is also cleared, when i truncat the table.
It seems to me that your problem lies in trying to truncate the table and manually clearing your local version of the DbSet. You should just change your EF entities and save them, then those changes are reflected in the database.
This should work:
_lisDatabase.SortedTubes.RemoveRange(_lisDatabase.SortedTubes);
_lisDatabase.SortedTubes.Add(new SortedTube());
_lisDatabase.SaveChanges();
Alternatively, try this:
https://stackoverflow.com/a/10450893/5392513
I suspected that you retrieve the entiries from database with same context by tracking before Truncate the table and when you apply the SaveChanges the EF is trying to delete already deleted records by Truncate. So, usual way to perform it creating a new instance from context and apply actions. It is not good idea to make long database processes with same context. So, in your case if you want to truncate table and use the same context to add new entries later you should detach all tracked entries after truncate action.
public void ResetStatistics()
{
_lisDatabase.Database.ExecuteSqlCommand("TRUNCATE TABLE Sortedtubes");
_lisDatabase.sortedtubes.Local.Clear();
foreach (var entry in _lisDatabase.ChangeTracker.Entries<Sortedtubes>())
{
_lisDatabase.Entry(entry).State = EntityState.Detached;
}
}
Also, if it is possible use .AsNoTracking in your queries before Truncate the table and no need to detach entries manually.
So.. finaly i think i got a solution.
My reset method looks like this now:
public void ResetStatistics() {
_lisDatabase.sortedtubes.RemoveRange(_lisDatabase.sortedtubes);
_lisDatabase.SaveChanges();
}
And my add stays the same:
_lisDatabase.sortedtubes.Add(tube);
_lisDatabase.SaveChanges();
but the "big" change was in my Sortedtubes entity. I changed the type of Time from DateTime to a normal String
from:
[Key]
[Column(Order = 1)]
public DateTime? Time { get; set; }
to:
[StringLength(45)]
public string Time { get; set; }
The problem seems to be the Type of the Time property of the Sortedtubes Entity. But i don`t know why.
If anyone wants to explain me this case?
Thanks to all for your help.

C# Entity Model won't correctly save changes to SQL database

Here's a brief summary of my code - it was written a long time ago and there are over 50 properties all written this way, yet when I added a new one, both in the model and within the ViewModel, it refuses to save changes:
From the view I have:
#Html.EditorFor(m => m.PhoneNumber )
From the ViewModel I have:
public string Registration {get;set;}
From the controller we have:
public async Task<ActionResult> SaveVehicleInfo(VehicleViewModel VM){
Vehicle vehicle = Mapper.Map<VehicleViewModel, Vehicle>(VM); (Automapper library)
var changes = false;
Vehicle dbVehicle = await context.Vehicles.FindAsync(vehicle.ID)
//A load more properties etc
string PhoneNumberChange = "";
if (dbVehicle.PhoneNumber != vehicle.PhoneNumber)
{
PhoneNumberChange = " - Phone Number changed to " + vehicle.PhoneNumber + " from " + dbVehicle.PhoneNumber;
dbVehicle.PhoneNumber = vehicle.PhoneNumber;
changes = true;
}
//At the end:
_db.Vehicles.Attach(dbVehicle);
_db.Entry(dbVehicle).State = EntityState.Modified;
_db.Notes.Add(note);
try
{
await _db.SaveChangesAsync();
}
catch (Exception e) {
var str = "";
}
return #stuff#;
}
I know this is not the best way of doing it, as I said it was written a long time ago.
On inspecting the item dbVehicle in this line:
_db.Entry(dbVehicle).State = EntityState.Modified;
It correctly shows the dbVehicle.PhoneNumber as being my new value. It also shows this:
PhoneNumberChange = " - Phone Number changed to NEWVALUE from OLDVALUE"
The save statement goes through, however SQL logs do not show the PhoneNumber even being included in the UPDATE statement. ALL other values save correctly, except this new one I've just done. I can manually enter it in the database, the savechangesasync method fires without throwing anything, I just cannot figure out why it's doing this.
Have cleaned/rebuilt whole solution. No idea what's going on.
Entity Framework Version 6.
I think perhaps this was something going wrong in Entity Framework somewhere. After a lot of messing around, deleting the model and re-adding it seemed to fix the problem.

LINQ: SubmitChanges() not updating my record

Not to sound like a broken record here (there a few posts that look like this one) but none of them seem to solve my problem. It seems that when you want to update
private bool resetPassword(string password)
{
try
{
var db = new SchedulerDBDataContext();
// since this is a instance method, I grab the ID from _this_
AdminUser user = db.AdminUsers.SingleOrDefault(t => t.ID == _ID);
if (user != null)
{
// this method DOES update these two fields.
SchedUtil.md5Hash(password, ref user._EncryptedPassword, ref user._PasswordSalt);
// I threw these in there to try something... it didn't work.
//user._EncryptedPassword = user.EncryptedPassword;
//user._PasswordSalt = user.PasswordSalt;
// this DOESN'T do anything.
db.SubmitChanges();
return true;
}
return false;
}
catch (Exception)
{
return false;
}
}
Maybe this a dumb question but I'm retrieving this from the db... why not just update this's properties. I'm guess I need to pull it through the DBContext I guess.
You should be setting the public properties and not the private values.
// I threw these in there to try something... it didn't work.
//user._EncryptedPassword = user.EncryptedPassword;
//user._PasswordSalt = user.PasswordSalt;
This won't trigger any updates.
Even if you do :
user.EncryptedPassword = user._EncryptedPassword;
user.PasswordSalt = user._PasswordSalt;
this won't trigger any change either as you are not actually changing the values
You can do something like
string newEncryptedPassword;
string newPasswordSalt;
SchedUtil.md5Hash(password, ref newEncryptedPassword, ref newPasswordSalt);
user.EncryptedPassword = newEncryptedPassword;
user.PasswordSalt = newPasswordSalt;
Also check that your table has a primary key, otherwise Linq will not track the changes.
DJ,
Are you sure
user._EncryptedPassword ,
user._PasswordSalt
are the properties ? I think you LINQ TO SQL creates public and private properties.
Can you set them
user.EncryptedPassword ,
user.PasswordSalt
like this ?
Ved
To troubleshoot your code, try any of these suggestions:
while debugging the code, I'll assume that your object is not null.
ensure that your properties are actually changed. It's odd that you're using pipe-prefixed field names, but either way: while debugging, check that your properties actually have new values.
use SQL Server Profiler to capture the SQL statement sent to the database server. You'll then be able to re-run this UPDATE query back into SQL Management Studio, and determine how many records are effected. You'll also be able to see the values passed in the UPDATE statement.
Ved pointed out one possible problem. Just in case that doesn't work, you should double check your LINQ to SQL class' AdminUser class definition and make sure that the generated code implements the INotifyPropertyChanging and INotifyPropertyChanged interfaces. There are some cases where the designer will not implement these interfaces which prevents updates from working. e.g., not declaring a primary key.

Categories