我正在尝试保存对现有数据库条目的更新,但是当我这样做时,我收到错误:
附加“FFInfo.DAL.Location”类型的实体失败,因为同一类型的另一个实体已具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图表,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。
这是我的控制器代码。我正在使用的保存方法与我在其他几个方面使用的保存方法相同,可以毫无问题地更新数据。
[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);
}
}
这是我的位置实体代码:
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; }
}
这是我第一次尝试更新这样一个更复杂的实体,但是从我在网上找到的内容中我看不出任何错误。
答案 0 :(得分:14)
在Entity Framework中,内存中不能有两个具有相同主键的实体(相同类型)。
问题是
model.ParentLocations = new SelectList(db.Locations.Where(l => l.SectionID == model.Section).OrderBy(l => l.Name), "ID", "Name").ToList();
在上面一行中你以某种方式加载了Location
ID
为model.ID
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;
然后在
Location
您正在创建新的Location
并尝试将其附加到上下文(通过将其状态设置为已修改),但您已加载另一个UpdatedLocation
实体,其中包含完全主键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;
进入某个地方的内存,这会导致异常。
尝试获取位置,然后更改属性。
re module
答案 1 :(得分:0)
尝试通过id获取实体,而不是创建具有固定ID的新实体:
var UpdateLocation = db.Locations.FirstOrDefault( l => l.ID == model.ID );
UpdateLocation.Description = model.Description;
...
您看到异常的原因是因为您的
model.ParentLocations = ...
实现最有可能包含您尝试修改的实体的实体。因此,该实体已经处于第一级缓存中。
但是你试着假装另一个存在相同身份的实体。
答案 2 :(得分:0)
我刚刚创建了一个 contextEntity 的新实例并且代码运行良好