0

I have a method to update data from a CSV with a DbContext. I deliberately uploaded some bad data so that I could test the output when there's a validation error. The data I uploaded had an invalid state, so I got the error Test.Entry@aol.com has the following validation errors:-"Field: "State", Error: "The field State must be a string or array type with a maximum length of '2'."

However, I then fixed the data, but continued to get the same error. I then tried to upload some completely different data - e.g. DifferentEntry@gmail.com - and still have the same validation error, for Test.Entry@aol.com even though I'm not creating an entry with that email address at all.

        try
        {
            var success = _dbContext.SaveChanges() > 0;
            return success ? "Done! Please reload the page" : "Failed to update entries";
        }
        catch (DbEntityValidationException e)
        {
            var output = "FAILED TO SAVE CHANGES TO DATABASE. Please see the following validation errors:<br/>";
            foreach (var eve in e.EntityValidationErrors)
            {
                output += String.Format("{0} has the following validation errors:",
                    eve.Entry.Property("Email").CurrentValue);
                foreach (var ve in eve.ValidationErrors)
                {
                    output += String.Format("- Field: \"{0}\", Error: \"{1}\"<br/>",
                        ve.PropertyName, ve.ErrorMessage);
                }
            }
            return output;
        }

I stepped through the code and confirmed that the entry being created is correct, that all of the values are what I have in my CSV file, but then it throws the exception for the old data. Why is it still trying to save a previous entry, and how do I get rid of it?

A bit more information:

public class EntriesRepository : CachableBase, IEntriesRepository
{
    private readonly IeBusinessEntities _ieBusinessEntities;

    public EntriesRepository(IeBusinessEntities ieBusinessEntities)
    {
        _ieBusinessEntities = ieBusinessEntities;
    }

    public class UpdateEntries(List<Entry> entries){
        foreach (var entry in entries){
              _ieBusinessEntities.Entries.Add(entry);
        }


        [the Try/Catch from above, with var success = _ieBusinessEntities.SaveChanges() > 0;]
    }
    
    .....

eBusinessEntities inherits DbContext

Erica Stockwell-Alpert
  • 4,624
  • 10
  • 63
  • 130

1 Answers1

0

I resolved it by adding a method to dispose of all changed on error, copied from https://stackoverflow.com/a/16438187/3784238. I'm still not sure why this was necessary though, would be great if anyone could answer that

public void DiscardChanges()
{
    ChangeTracker.DetectChanges();

    //get all entries that are changed
    var entries = ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged).ToList();

    //somehow try to discard changes on every entry
    foreach (var dbEntityEntry in entries)
    {
        var entity = dbEntityEntry.Entity;

        if (entity == null) continue;

        if (dbEntityEntry.State == EntityState.Added)
        {
            //if entity is in Added state, remove it. (there will be problems with Set methods if entity is of proxy type, in that case you need entity base type
            var set = Set(entity.GetType());
            set.Remove(entity);
        }
        else if (dbEntityEntry.State == EntityState.Modified)
        {
            //entity is modified... you can set it to Unchanged or Reload it form Db??
            dbEntityEntry.Reload();
        }
    }
}
Erica Stockwell-Alpert
  • 4,624
  • 10
  • 63
  • 130