Entity Framework - When editing, fails in "db.Entry (category) .State = EntityState.Modified;"

0

I have a "Category" Entity, which contains id, name, created, and updated. I'm using Code First.

This is my template:

public class Category
{
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public DateTime Created { get; set; }
    public DateTime Updated { get; set; }

    public virtual ICollection<Item> Items { get; set; }
}

The controller was generated by scaffolding , that is, it came ready, but I made some changes due to the fact that I want the created and updated < ) are automatic.

In the create method, see the change I made:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "CategoryId,Name,Created,Updated")] Category category)
    {
//Eu inseri este trecho
        if(category.Created == null || category.Created == Convert.ToDateTime("01/01/0001 00:00:00"))
        {
            category.Created = DateTime.Now;
        }
        category.Updated = DateTime.Now;
//termina aqui

        if (ModelState.IsValid)
        {
            db.Categories.Add(category);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(category);
    }

This works fine. When I create a new category, it assigns these values to the attribute and saves them correctly. The problem appears at the time of editing.

Look at the changes I made to the controller generated by the Entity Framework itself:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "CategoryId,Name,Created,Updated")] Category category)
    {          
//Eu inseri este trecho  
        category.Created = db.Categories.Find(category.CategoryId).Created;
        category.Updated = DateTime.Now;
//Termina aqui

        if (ModelState.IsValid)
        {
            db.Entry(category).State = EntityState.Modified; // Da erro aqui
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(category);
    }

When it arrives in the "EntityState.Modified, it brings up the following error message:

  

An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code

     

Additional information: Attaching an entity of type 'Entities.Model.Category' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

I am reviewing and understanding the following: The error only occurs when I use find and I bring the BD record. But why is this happening? What the heck of an entity that is already using the same primary key ? Can someone give me a light?

    
asked by anonymous 31.03.2017 / 17:01

2 answers

2

Do not get me wrong, but the solution to this is horrible.

The error happens because of this:

    //Eu inseri este trecho  
    category.Created = db.Categories.Find(category.CategoryId).Created;
    category.Updated = DateTime.Now;
    //Termina aqui

First you selected the category of the bank, then asked the context to observe the same category that came from the screen:

db.Entry(category).State = EntityState.Modified; // Da erro aqui

It will make a mistake. The context can observe an object with the same primary key at a time. Selecting by .AsNoTracking() makes the code easily come into bad practice.

This field fill is not done this way. I teach how to do it here .

    
10.05.2017 / 22:04
0

I solved an identical problem using the solution below:

category.Created = db.Categories.AsNoTracking().Where(x => x.CategoryId == category.CategoryId).FirstOrDefault();

With AsNoTracking (), entities will be read from the source of their data, but will not be kept in context.

Hope this helps!

    
10.05.2017 / 21:58