I am trying to save an update to an existing database entry but when I do I get the error:
Attaching an entity of type 'FFInfo.DAL.Location' 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 yet 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.
This is my controller's code. The save method I am using is the same I use in a few other areas to update data with no problems.
[HttpPost, ValidateAntiForgeryToken]
public ActionResult EditLocation(AddEditLocationVM model, HttpPostedFileBase MapFile)
{
try
{
using (var db = new GeographyContext())
{
model.Sections = new SelectList(db.Sections.Where(s => s.ID > 1).OrderBy(s => s.Title), "ID", "Title").ToList();
model.GeographyTypes = new SelectList(db.GeographyTypes.Where(gt => gt.SectionID == model.Section).OrderBy(gt => gt.Name), "ID", "Name").ToList();
model.ParentLocations = new SelectList(db.Locations.Where(l => l.SectionID == model.Section).OrderBy(l => l.Name), "ID", "Name").ToList();
if (MapFile != null)
{
if (FileHelper.IsNotValidImage(MapFile))
{
ModelState.AddModelError("Invaalid File Type", "Images must be JPG, GIF, or PNG files.");
}
}
if (ModelState.IsValid)
{
if (MapFile != null)
{
var SectionRoute = db.Sections.Where(s => s.ID == model.Section).Select(s => s.Route).First();
model.MapFileID = FileHelper.UploadFile("Images/" + SectionRoute + "/Maps/" + MapFile.FileName.ToList(), "site", MapFile);
}
if (model.ParentLocation == 0)
{
model.ParentLocation = null;
}
var UpdatedLocation = new Location()
{
Description = model.Description,
GeographyTypeID = model.GeographyType,
ID = model.ID,
MapFileID = model.MapFileID,
Name = model.Name,
ParentLocationID = model.ParentLocation,
SectionID = model.Section
};
db.Entry(UpdatedLocation).State = EntityState.Modified;
db.SaveChanges();
ViewBag.Results = "Location information updated.";
}
return View(model);
}
}
catch (Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
model.Sections = Enumerable.Empty<SelectListItem>();
ViewBag.Results = "Error updating location informaiton, please try again later.";
return View(model);
}
}
This is my Location Entity code:
public class Location
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Required, Index("IX_Location", 1, IsUnique = true)]
public string Name { get; set; }
[Index("IX_Location", 2, IsUnique = true)]
public Int16 SectionID { get; set; }
[Column(TypeName = "varchar(MAX)")]
public string Description { get; set; }
public Int16 GeographyTypeID { get; set; }
public int? MapFileID { get; set; }
public int? ParentLocationID { get; set; }
[ForeignKey("SectionID")]
public Section Section { get; set; }
[ForeignKey("GeographyTypeID")]
public GeographyType GeographyType { get; set; }
[ForeignKey("MapFileID")]
public File Map { get; set; }
[ForeignKey("ParentLocationID")]
public Location ParentLocation { get; set; }
public ICollection<LocationTransitionPoint> TransitionPoints { get; set; }
}
This is my first time trying to update a more complex entity like this but from what I have found on the web I can not see anything wrong.
You cannot update the primary key through entity framework, since entity framework would not know which database row to update. However, if you really need to do it, you could write a stored procedure that updates the primary key, and then execute the stored procedure from entity framework.
How to Update a new record in to a existing entity using update entity action? First you need to check the id if id exist then you can use the update entity action and if id is new then you can used the create entity action.
Add() method attaches the entire entity graph to a context and automatically applies the Added state to all entities. The DbSet. Add() method attaches the entire entity graph to a context with the Added state to each entity. Calling context.
You can not have two entities (same type) with same primary keys in memory in Entity Framework.
The problem is
model.ParentLocations = new SelectList(db.Locations.Where(l => l.SectionID == model.Section).OrderBy(l => l.Name), "ID", "Name").ToList();
in above line you somehow have loaded the Location
which its ID
is model.ID
then in
var UpdatedLocation = new Location()
{
Description = model.Description,
GeographyTypeID = model.GeographyType,
ID = model.ID,
MapFileID = model.MapFileID,
Name = model.Name,
ParentLocationID = model.ParentLocation,
SectionID = model.Section
};
db.Entry(UpdatedLocation).State = EntityState.Modified;
You are creating a new Location
and trying to attach it to context (by setting it's state as modified), but you have loaded another Location
entity with exact primary key as UpdatedLocation
into memory somewhere and this cause the exception.
Try fetching the the location and then change the roperties.
var UpdateLocation = db.Locations.First(l => l.ID == model.ID);
// var UpdateLocation = db.Locations.Find(model.ID); maybe a better option
UpdatedLocation.Description = model.Description;
UpdatedLocation.GeographyTypeID = model.GeographyType;
UpdatedLocation.MapFileID = model.MapFileID;
UpdatedLocation.Name = model.Name;
UpdatedLocation.ParentLocationID = model.ParentLocation;
UpdatedLocation.SectionID = model.Section;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With