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

asp.net asp.net-mvc entity-framework entity-framework-6 optimistic-concurrency

Question

I use Entity Framework 6 in an MVC 5 project an there is an entity relations between Experiment and FileAttachment (one Experiment can gave many FileAttachment). During Edit an Experiment record, I load a ViewModel containing both of the entities and list the attachments under the experiment in edit mode:

The scenario is as explained below:

1) There is a Delete button for each FileAttachment and when user delete an attachment, it is deleted via AJAX and display an information message on the same modal window.

2) But, if the user add a new attachment after deleting an attachment and save the Experiment the following error is encountered:

"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded."

  • I think the reason is that: I load Experiment and FileAttachment entities and then I change the FileAttachment entity by deleting a record. But there is still the same entity loaded first time and I want to save the outdated entity. So, maybe I need to create an entity and fill it before saving, but context.Entry(f).State = EntityState.Added, context.Entry(f).State = EntityState.Modified and context.Entry(f).State = EntityState.Unchanged does not make any sense. What should I do to simply attach the newly added FileAttachment to the database?

Models:

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; }
}

ViewModel:

public class ExperimentViewModel
{
    //code omitted for brevity

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

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

Controller:

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);
}

Concrete:

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(); 
    }
}


1
2
10/10/2016 12:10:55 PM

Popular Answer

Here is the final answer by fixing the problems with the help of @StephenMuecke and @haim770. Many thanks both of you for your effort and kind help... Regards.

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();
    }
}
0
10/10/2016 12:00:04 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow