c# – 在尝试保存更新时,由于相同的主键而附加实体时出错

我正在尝试保存对现有数据库条目的更新,但是当我这样做时,我收到错误

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.

这是我的控制器代码.我正在使用的保存方法与我在其他几个方面使用的保存方法相同,可以毫无问题地更新数据.

[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),"Name").ToList();
            model.ParentLocations = new SelectList(db.Locations.Where(l => l.SectionID == model.Section).OrderBy(l => l.Name),"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; }
}

这是我第一次尝试更新这样一个更复杂的实体,但是从我在网上找到的内容我看不出有什么不对.

解决方法

实体框架中的内存中不能有两个具有相同主键的实体(相同类型).

问题是

model.ParentLocations = new SelectList(db.Locations.Where(l => l.SectionID == model.Section).OrderBy(l => l.Name),"Name").ToList();

在上面的行中你以某种方式加载了它的ID为model.ID的Location

然后在

var UpdatedLocation = new Location()
{
    Description = model.Description,SectionID = model.Section
};
db.Entry(UpdatedLocation).State = EntityState.Modified;

您正在创建一个新位置并尝试将其附加到上下文(通过将其状态设置为已修改),但您已将另一个具有精确主键的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;

相关文章

在项目中使用SharpZipLib压缩文件夹的时候,遇到如果目录较深,则压缩包中的文件夹同样比较深的问题。比...
项目需要,几十万张照片需要计算出每个照片的特征值(调用C++编写的DLL)。 业务流程:选择照片...
var array = new byte[4]; var i = Encoding.UTF8.GetBytes(100.ToString(&quot;x2&quot;));//...
其实很简单,因为Combox的Item是一个K/V的object,那么就可以把它的items转换成IEnumerable&lt;Dic...
把.net4.6安装包打包进安装程序。 关键脚本如下: 头部引用字符串对比库 !include &quot;WordFunc....
项目需求(Winform)可以批量打印某个模板,经过百度和摸索,使用iTextSharp+ZXing.NetʿreeSp...