BuddyJoe
BuddyJoe

Reputation: 71101

SaveChanges() from an EntityFramework context fails silently

I am using an Entity Framework 6.1 Model from Database 'wizard' setup. When I create a Business object from my context and then try to add for attachment and then SaveChanges() nothing happens. Is there a tracing mode? or something I can turn on to see what is really happened under the covers.

Simple example:

 var fb = _context.Business.Create();
 //fb.Id exists and is an int but it is auto incr in the db
 fb.Name = ub.ACCOUNT_NAME;
 fb.ServiceManager = ub.SERVICE_MANAGER;
 fb.AccountManager = ub.ACCOUNT_MANAGER;
 fb.SalesPerson = ub.SALESPERSON;
 fb.Created = DateTime.UtcNow;
 fb.Updated = DateTime.UtcNow;
 _context.Add(fb);
 _context.SaveChanges();

Upvotes: 2

Views: 5529

Answers (3)

GELR
GELR

Reputation: 1293

The best way I have found to catch EF errors is by overriding the SaveChange method like below. If you have a centered place to recover logs (like log4net), the function will be able to insert it there.

public partial class Business
{
    /// <summary>Override the SaveChange to return better error messages</summary>
    public override int SaveChanges()
    {
        try {
            return base.SaveChanges();
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException ex) {
            // Retrieve the error messages as a list of strings.
            var errorMessages = ex.EntityValidationErrors
                    .SelectMany(x => x.ValidationErrors)
                    .Select(x => x.ErrorMessage);

            // Join the list to a single string.
            var fullErrorMessage = string.Join("; ", errorMessages);

            // Combine the original exception message with the new one.
            var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);

            // Add some logging with log4net here


            // Throw a new DbEntityValidationException with the improved exception message.
            throw new System.Data.Entity.Validation.DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);

        }
    }

Upvotes: 7

BenG
BenG

Reputation: 15154

Have you tried creating a new Business object and adding it in? instead of creating one first?

 var fb = new Business();
 //fb.Id exists and is an int but it is auto incr in the db
 fb.Name = ub.ACCOUNT_NAME;
 fb.ServiceManager = ub.SERVICE_MANAGER;
 fb.AccountManager = ub.ACCOUNT_MANAGER;
 fb.SalesPerson = ub.SALESPERSON;
 fb.Created = DateTime.UtcNow;
 fb.Updated = DateTime.UtcNow;
 _context.Business.Add(fb);
 _context.SaveChanges();

Upvotes: 0

CJR
CJR

Reputation: 61

Have you tried checking for any validation errors?

Here is the try block and validation method I am using in one of my new classes, so treat it as a code sample and not a 100% tested solution as I am still putting together some unit tests:

public List<string> ValidationErrorList = new List<string>();


try
{
  _context.SaveChanges();
}
catch (Exception)
{
  GetErrors(_context);
}

private void GetErrors(System.Data.Entity.DbContext context)
{

  IEnumerable<System.Data.Entity.Validation.DbEntityValidationResult> ve;

  ve = context.GetValidationErrors();
  ValidationErrorList.Clear();

  foreach (var vr in ve)
  {
    if (vr.IsValid == false)
    {
      foreach (var e in vr.ValidationErrors)
      {
        var errorMessage = e.PropertyName.Trim() + " : " +
                           e.ErrorMessage;
        ValidationErrorList.Add(errorMessage);
      }
    }
  }
}

While the above sample only calls the GetErrors method when an exception is triggered, you might also want to try calling it right after the SaveChanges() to see if there are validation errors that are not throwing an exception.

Upvotes: 0

Related Questions