繁体   English   中英

如何避免EF中新添加记录的乐观并发错误

[英]How to avoid optimistic concurrency error for newly added record in EF

我在MVC 5项目中使用Entity Framework 6,在Experiment和FileAttachment之间存在实体关系(一个Experiment可以提供多个FileAttachment)。 在“编辑实验”记录期间,我加载了一个包含两个实体的ViewModel并在编辑模式下列出了该实验下的附件:

该方案如下所述:

1)每个FileAttachment都有一个Delete按钮,当用户删除附件时,它会通过AJAX删除并在同一模式窗口中显示一条信息消息。

2)但是,如果用户在删除附件后添加新附件并保存实验,则会遇到以下错误:

“存储更新,插入或删除语句影响了意外的行数(0)。自加载实体以来,实体可能已被修改或删除。”

  • 我认为原因是:我加载了Experiment和FileAttachment实体,然后通过删除一条记录来更改FileAttachment实体。 但是仍然有第一次加载的相同实体,我想保存过时的实体。 因此,也许我需要创建一个实体并在保存之前填充它,但是context.Entry(f).State = EntityState.Added, context.Entry(f).State = EntityState.Modifiedcontext.Entry(f).State = EntityState.Unchanged没有任何意义。 我应该怎么做才能简单地将新添加的FileAttachment附加到数据库

楷模:

public class Experiment
{
    [Key]
    public int Id { get; set; }

    public int Number { get; set; }

    public string Name { get; set; }

    //Navigation Properties 
    public virtual ICollection<FileAttachment> FileAttachments { get; set; }
}



public class FileAttachment
{
    [Key]
    public int Id { get; set; }

    public int ExperimentId { get; set; }

    public string FileName { get; set; }

    public byte[] FileData { get; set; }

    [HiddenInput(DisplayValue = false)]
    public string FileMimeType { get; set; }

    //Navigation Properties 
    public virtual Experiment Experiment { get; set; }
}

视图模型:

public class ExperimentViewModel
{
    //code omitted for brevity

    [DataType(DataType.Upload)]
    public IEnumerable<HttpPostedFileBase> FileUpload { get; set; }

    public virtual ICollection<FileAttachment> FileAttachments { get; set; }
}

控制器:

public JsonResult Update([Bind(Exclude = null)] ExperimentViewModel model)
{
    List<FileAttachment> fa = new List<FileAttachment>();
    //code omitted for brevity (At this step I add all the attachments in the model to "fa" paarmeter)

    //Mapping ViewModel to Entity Model (ExperimentViewModel > Experiment) :::::::::::::::::
    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<ExperimentViewModel, Experiment>();
    });

    IMapper mapper = config.CreateMapper();
    //var source = new ExperimentViewModel();
    var dest = mapper.Map<ExperimentViewModel, Experiment>(model);
    ////::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    repository.SaveExperimentWithAttachment(dest, fa);
}

具体:

public void SaveExperimentWithAttachment(Experiment experiment, IEnumerable<FileAttachment> fileAttachment)
{ 

    //Update Block 
    using (var context = new EFDbContext())
    {
        context.Entry(experiment).State = EntityState.Modified;
        foreach (FileAttachment f in fileAttachment)
        {
            context.Entry(f).State = EntityState.Modified;
        }
        context.SaveChanges(); 
    }
}


这是通过@StephenMuecke@ haim770修复问题的最终答案。 非常感谢你们的努力和帮助。

public void SaveExperimentWithAttachment(Experiment experiment, IEnumerable<FileAttachment> fileAttachment)
{
    using (var context = new EFDbContext())
    {
        context.Entry(experiment).State = EntityState.Modified;
        foreach (FileAttachment f in fileAttachment)
        {
            // !!! I forgot to update the ExperimentId field for each file attachment
            f.ExperimentId = experiment.Id;
            context.Entry(f).State = EntityState.Added; //Because file attachment(s) is not updated, newly ADDED
        }
        context.SaveChanges();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM