0

So I am having a problem catching the exception for adding a new record to the database.

I am using Entity Framework

enter image description here

Here is my code:

public void AddNewStandardEngineeredModel(StandardEngineeredModel model)
    {
        using (context = new LabelPrintingContext())
        {

            try
            {
                context.EngineeredModels.Add(model);
                context.SaveChanges();
            }
            catch (SqlException ex)
            {
                if (ex.Number == 2601)
                {
                    //Violation of primary key. Handle Exception
                }
                else throw;
            }
        }
    }

I have also tried the following:

 public void AddNewStandardEngineeredModel(StandardEngineeredModel model)
    {
        using (context = new LabelPrintingContext())
        {

            try
            {
                context.EngineeredModels.Add(model);
                context.SaveChanges();
            }
            catch (UpdateException ex)
            {
                var sqlException = ex.InnerException as SqlException;

                if (sqlException != null && sqlException.Errors.OfType<SqlError>()
                    .Any(se => se.Number == 2601))
                {

                    // it's a dupe... do something about it
                }
                else
                {
                    // it's something else...
                    throw;
                }
            }
        }
    }

If I just do catch(Exception Ex) it will catch the exception but I want to check the number to give a better response to my user. That way if a duplicate is about to be added I can let them know and fix it appropriately.

Here is a picture of the error:

enter image description here

Not quite sure what else to try and catch the specific exception. Any suggestions would help.

Eric Obermuller
  • 245
  • 3
  • 19
  • at least say what is your `model`'s primary key, is it an Identity? it seems that your logic has a bug. inserting(filling) `ID`. – ahmad molaie Jul 10 '18 at 20:12
  • _I want to check the number to give a better response to my user. That way if a duplicate is about to be added I can let them know and fix it appropriately._ Simple. Don't let your users specify the primary key. – stuartd Jul 10 '18 at 20:31
  • Primary Key is a string. The model number is the primary key. I just want to know how to handle the exception. – Eric Obermuller Jul 10 '18 at 20:31
  • Well I don't want duplicate model numbers in the database so setting my model number as the primary key would make the most sense. – Eric Obermuller Jul 10 '18 at 20:32
  • I am just wondering why the exception is not being caught by these catch() statements, not about what my primary key is etc, I know the primary key being a duplicate is the problem, the way the program works is, it will try to add the model, if a Duplicate key exception is thrown, instead of trying to add it I want to ask the user if they want to update the record instead. – Eric Obermuller Jul 10 '18 at 20:34
  • Possible duplicate of [Catching exceptions with "catch, when"](https://stackoverflow.com/questions/38497774/catching-exceptions-with-catch-when) – mjwills Jul 10 '18 at 21:52

1 Answers1

1

When using an ORM, the SqlException is often going to be wrapped, sometimes nested quite a bit. So you need a helper function to walk the exception tree and find the SqlException (if it's there):

    static SqlException GetSqlException(Exception exception)
    {
        if (exception is SqlException sqlException) return sqlException;
        return exception.InnerException == null ? null : GetSqlException(exception.InnerException);
    }

Then, you can use whatever strategy you like for catching however fine-grained an exception, and dealing with the SqlException if it's found. e.g. based on your code:

public void AddNewStandardEngineeredModel(StandardEngineeredModel model)
{
    using (context = new LabelPrintingContext())
    {

        try
        {
            context.EngineeredModels.Add(model);
            context.SaveChanges();
        }
        catch (Exception ex)
        {
            var sqlException = GetSqlException(ex);

            if (sqlException != null && sqlException.Errors.OfType<SqlError>()
                .Any(se => se.Number == 2601))
            {

                // it's a dupe... do something about it
            }
            else
            {
                // it's something else...
                throw;
            }
        }
    }
}
David Moore
  • 2,466
  • 22
  • 13
  • This is perfect thank you. Worked out great. Its kind of annoying that the exception is wrapped so much. Went through it like 4 times before it found the exception I wanted. – Eric Obermuller Jul 11 '18 at 00:54