Iam trying to edit information from a table in my database. I can insert the information into the table, but when I try to edit that info, I got the following error message. Any help? please
System.Data.Entity.Validation.DbEntityValidationException: 'Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.'
This is my controller Edit: I got the error in the " context.SaveChanges(); " line
[HttpGet]
public ActionResult Editar(int id)
{
Cafeteria_POSEntities context = new Cafeteria_POSEntities();
Faculty empleado = context.Faculties.Single(x => x.Employee_ID == id);
ViewBag.Meal_Plan = GetPlanesSelect();
return View(empleado);
}
[HttpPost]
[ActionName("Editar")]
public ActionResult Editar(Faculty empleado)
{
if (ModelState.IsValid)
{
Cafeteria_POSEntities context = new Cafeteria_POSEntities();
context.Entry(empleado).State = EntityState.Modified;
context.SaveChanges();
return RedirectToAction("Index");
}
return View(empleado);
}
The 'DbEntityValidationException' is an exception that suggests problems with the data you are trying to insert/update in your context/database. I cannot see here because there is not provided input data or the table in your database, but I would say that you either, have a wrong data type for some property, some property might be null which is not allowed, or maybe breaking some primary/foreign key rules.
Related
Hello I am trying to edit my table in db and is give me this error An update, insert, or delete instruction in the store has affected an unexpected number of rows (0). Entities may have been modified or deleted since loading.
trying many test and when i'm arrive on SaveChange is stop process
and incomplete operaion
This is the implementation
public ActionResult Edit(int? id)
{
db = new IdentityDBEntities();
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Article article = db.Articles.Find(id);
if (article == null)
{
return HttpNotFound();
}
ViewBag.Idc = new SelectList(db.Categories, "Id", "libelle", article.Idc);
return View(article);
}
// POST: Articles/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Ida,description,UserId,Idc,titre,image")] Article article, HttpPostedFileBase image)
{
if (ModelState.IsValid)
{
if (image != null)
{
article.image = image.FileName;
}
db = new IdentityDBEntities();
article.UserId = System.Web.HttpContext.Current.User.Identity.GetUserId();
db.Entry(article).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.Idc = new SelectList(db.Categories, "Id", "libelle", article.Idc);
return View(article);
}
Article was loaded in one instance of a DbContext, and you are attempting to save it with another instance. The entity would need to be associated to the new context before being saved. (I.e. Attach or Update) However, I do not recommend this approach.
As a general rule you should avoid passing entities to and from a web client. If you accept an entity to a web client, it is a simple matter to find the call passing the modified entity to the server, apply a breakpoint, and modify the contents using the debugger before resuming. If the server merely attaches the entity to a context and saves the changes, I can modify data in ways the application should not allow. It also involves sending more information to/from the client than is typically necessary.
You also run into the problem that the data supporting an entity loaded at one point in your current session has been modified by another session between the time you read the data, and the time you're prepared to update it. Systems should not merely attach and overwrite data without first verifying (via something like a Timestamp or last modified date/time) that the data hasn't been updated since the entity was loaded. From there the system can take an appropriate action. (log that data will be overwritten, overwrite, or merge & notify the user to review their changes.)
edit: To outline an example.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Ida,description,UserId,Idc,titre,image")] Article article, HttpPostedFileBase image)
{
if (!ModelState.IsValid)
{
ViewBag.Idc = new SelectList(db.Categories, "Id", "libelle", article.Idc);
return View(article);
}
using (var db = new IdentityDBEntities())
{
var existingArticle = db.Articles.Single(x => x.ArticleId == article.ArticleId);
if (existingArticle.RowVersion != article.RowVersion) // Or compare LastModifiedDateTime etc.
{
// Set a validation state to tell the user that the article had changed since they started editing. Perhaps merge values across, but send the article back.
return View(existingArticle);
}
if (image != null)
existingArticle.image = image.FileName;
existingArticle.UserId = System.Web.HttpContext.Current.User.Identity.GetUserId(); // can this be updated?
db.SaveChanges();
}
return RedirectToAction("Index");
}
The key differences:
DbContext's are disposable so should be wrapped in a using block.
We load the article from the context, check if it's been modified since we had originally loaded it. (other validation checks to ensure the user can modify this article would be prudent as well) if it isn't out of date and is valid, transfer the fields across and save the changes.
I am receiving this error:
"A referential integrity constraint violation occurred:
The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship."
when attempting to update my model from the front end. I did some research and saw a post that said I should null out my navigation properties to prevent this so I did but no luck. I have also tried reaching out and grabbing all the navigation properties and fully populating them so I have the full object, this too did not work.
I am using a really nice "generic repository" which handles the state changes and everything for me. When it goes into the update method it is attaching the record and blows up when doing so.
Here is the code that is setting up the object in my WebApi controller.
public HttpResponseMessage Put(ProductModel product)
{
if (!ModelState.IsValid)
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
var shopId = _uow.Repository<Shop>().GetShopIdByUserId("90f36c26-9b28-464d-869f-378015ae8f0c"); //work
product.ShopId = shopId;
var newProduct = Mapper.Map<Product>(product);
newProduct.Category = null;
try
{
_uow.Repository<Product>().Update(newProduct);
_uow.Save();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
This is the Repositories implementation for update. Id prefer not to touch this as it is part of the generic repository framework I am using.
public virtual void Update(TEntity entity)
{
_dbSet.Attach(entity); // **Blows up here**
((IObjectState)entity).State = ObjectState.Modified;
}
I am using WebApi v2, EF 6.
Edit:
I had a list of test data that should not have been sent to EF, i nulled it out and it works now. Funny how you can look at something 100x but not have it click until someone tells you to do the same thing lol!
This is the exception I get:
"An object with a key that matches the key of the supplied object could not be found in the ObjectStateManager. Verify that the key values of the supplied object match the key values of the object to which changes must be applied."
It is trown by the next line:
public void UpdateTransaction(Transaction transaction)
{
db.Transactions.ApplyCurrentValues(transaction);
}
I read on this page that the error might becouse it is not attached, but when I try to attach it I get another exception:
"An entity object cannot be referenced by multiple instances of IEntityChangeTracker."
By doing some reading that this means that the record is already attached to the model.
And when I try to detach it I get the next:
"The object cannot be detached because it is not attached to the ObjectStateManager."
This is my controller where I update the table "InputValue", now depending on the value I also want to make an update on the table "Transaction" wich is done by the updatedTransactions function.
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
var inputValue = inputValueRespository.GetInputValue(id);
if (inputValue == null)
return RedirectToAction("Index");
try
{
UpdateModel(inputValue, collection.ToValueProvider());
inputValue.InputValues_EditUser = WindowsIdentity.GetCurrent().Name;
inputValue.InputValues_EditDate = DateTime.Today.Date;
inputValueRespository.UpdateInputValue(inputValue);
List<Transaction> updatedTransactions = inputValueRespository.HasTransactions(inputValue.Input_ID, inputValue.InputValues_Date, inputValue.InputValues_Week, inputValue.InputValues_Quarter);
for (int i = 0; i < updatedTransactions.Count; i++)
{
transactionRepository.UpdateTransaction(updatedTransactions[i]);
}
inputValueRespository.save();
return RedirectToAction("Create");
}
catch (Exception)
{
return View("Create");
}
This is the function:
public List<Transaction> HasTransactions(int id, DateTime date, string week, string quarter)
{
// random code that decides if transaction should be update
Transaction transaction = new Transaction();
transaction = (from a in db.Transactions where a.KPI_ID == kpiId && a.Transaction_Period == period select a).SingleOrDefault();
// random code that generated new result
// fill the list of transaction that will be returned
transaction.Transaction_Value = result;
trasactions.Add(transaction);
}
}
return trasactions;
}
I'm completly clueless in this one, any help would be greatly appreciated.
PS: any other code where I use ApplyCurrentValue works perfectly.
I finally got it working ( by trial and error )
In the end I need the detach the object, attach it, modify, apply and then save.
db.Transactions.Detach(transaction);
db.Transactions.Attach(transaction);
transaction.Transaction_Value = result;
db.Transactions.ApplyCurrentValues(transaction);
db.SaveChanges();
Does not make a lot of sense but I guess it is just the way it works :)
I have found numerous posts with very similar problems as mine, but they all seem to use a DeleteObject() method that doesnt appear to exist in the version of EF i am using! (although its more than likely i am looking in the wrong places)
Anyway, my problem. I have two classes, User and Email where a user can have many emails. I have an edit form that will quite happily allow me to edit all email addresses attached to each user. I would like to allow each email address to be deleted simply by clearing the text box in the edit form (to be done using JavaScript function triggered by a remove button associated with each box later on). To this end, when the data is posted back, I loop through all the email addresses and test if the address property is null, at which point i want to delete that Email object completely. Below is my edit controller that is (not) doing the business:
[HttpPost]
public ActionResult Edit(int id, User User)
{
try
{
foreach (Email Email in User.Emails)
{
if (Email.Address == null)
{
User.Emails.Remove(Email);
}
else
{
db.Entry(Email).State = EntityState.Modified;
}
}
db.Entry(User).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return RedirectToAction("Index");
}
}
This works to a point, using the debugger i can see that it is quite happily removing the Email object from the User, but as soon as it has done that once it will throw an exception when it tries to go through the loop again:
Message=Collection was modified; enumeration operation may not execute.
my question: what is the correct method of deleting the Email object, not only from the User, but from my db too?
Thanks in advance ;-)
EDIT:
I have modified my controller to create two lists, one for Emails with and address and one for those where the address is null, and loop through those instead:
[HttpPost]
public ActionResult Edit(int id, User User)
{
try
{
var notNullEmails = User.Emails.Where(e => e.Address != null).ToList();
foreach (Email Email in notNullEmails)
{
db.Entry(Email).State = EntityState.Modified;
}
var isNullEmails = User.Emails.Where(e => e.Address == null).ToList();
foreach (Email Email in isNullEmails)
{
db.Emails.Remove(Email);
}
db.Entry(User).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return RedirectToAction("Index");
}
}
But that resulted in this exception:
Message=The object cannot be deleted because it was not found in the ObjectStateManager.
So i adapted the foreach used for the null addresses to explicitly pull the email to be deleted into the context like so:
var isNullEmails = User.Emails.Where(e => e.Address == null).ToList();
foreach (Email Email in isNullEmails)
{
Email EmailToDelete = db.Emails.Find(Email.Id);
db.Emails.Remove(EmailToDelete);
}
But that results in this exception:
Message=Value cannot be null.
I think i am getting there thanks to you guys, but i could use a little more help please :-)
You have two different problems:
One is, you can't remove items from a collection as you iterate the collection. Iterate through a List copy uoi make with .ToList() instead.
The other is, calling the Remove() method you are calling is only removing the relationship to the User - not actually removing it from the database. This would generate a referential integrity error, if the db enforces it.
Instead, You want to call Remove on the Emails DbSet.
context.emails.Remove(email);
Remove() is the method used by the DbContext. DeleteObject and RemoveObject are older/alternative APIs
I know you said about not using DeleteObject, but I had the same problem and thought I should post the answer here for others searching about this issue:
int i = User.Emails.Count - 1;
while (true)
{
if (i<0)
{
break;
}
Db.Emails.DeleteObject(User.Emails.ElementAt<Email>(i));
i--;
}
I know this is really old, but i thought i should probably answer it with the method i have found to actually work:
foreach(Email email in User.Emails)
{
if(string.IsNullOrEmpty(email.Address))
{
db.Entry(email).State = System.Data.EntityState.Deleted;
}
}
db.SaveChanges();
I think this is the simplest of any solution that i have seen so far, but feel free to correct me if there is a better way.
first of all here is the message
The changes to the database were
committed successfully, but an error
occurred while updating the object
context. The ObjectContext might be in
an inconsistent state. Inner exception
message: A referential integrity
constraint violation occurred: The
property values that define the
referential constraints are not
consistent between principal and
dependent objects in the relationship.
the problem happens when i try to insert new data in the entityframework
My entity model
in the database i set the relation to cascade on delete and update. that is the only change i made to the relation
My Action Method :
[HttpPost]
public ActionResult CompleteRegisteration(RegisterViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = new User
{
DisplayName = model.DisplayName,
FullName = model.Name,
Email = model.Email,
};
user.AuthenticationTokens.Add(new AuthenticationToken
{
ClaimedIdentifier = model.ClaimedIdentifier,
DisplayName = model.Email
});
_userRepository.InsertOrUpdate(user);
_userRepository.Save();
return RedirectToAction("Index", "Home");
}
and the user repository methods :
private readonly StoryWritingEntities context = new StoryWritingEntities();
public void InsertOrUpdate(User user)
{
context.Users.Attach(user);
context.ObjectStateManager.ChangeObjectState(user,
user.Id == default(int)
? EntityState.Added // if true then this is a new entry
: EntityState.Modified); // if false this is an Existing entry
}
public void Save()
{
context.SaveChanges();
}
the problem is caused by context.SaveChanges() there is a record inserted in the users table but nothing is inserted in the AuthenticationTokens table
If you simply did the following this wouldn't happen:
context.Users.AddObject(user);
content.SaveChanges();
I suspect the problem is occurring because EF doesn't know about the AuthenticationToken object, it's not being attached to the context because it's added to a disconnected entity which is then attached to the context.
You either need to let EF handle the whole object graph connectivity situation or you need to do it all yourself. Mixing and matching like this doesn't work.
Try something different, like:
if(model.Id != null)
{
UpdateModel(user);
}
else
{
_userRepository.Insert(model)
}
_userRepository.Save();
And the _userRepository.Insert would be:
public void Insert(User user)
{
context.Users.AddObject(user);
}
I got this error because I was trying to edit a record/row in the table, but the code was adding a row with the same ID.
So I just changed the
ctx.table.Add(entity object);
too
ctx.Entry(entity object).State = EntityState.Modified;
in the database i set the relation to
cascade on delete and update
1) I believe that if you setup cascading delete directly in the database you also need to define it in your model. The settings in the model designer are in the properties window of the relevant association (click on the association line between the two entities in the designer surface, then select "Properties").
2) I also believe that cascade on update is not supported in EF. Try to remove cascade on update in the database and check if it works then.