Универсальный способ поймать нарушение уникального ключа

Я использую System.Data.Common.DbCommand для вставки новой строки в базу данных. Дело в том, что этот ряд уже существует.

try
{
    [...]
    DbCommand insertCommand = [...]
    insertCommand.ExecuteScalar();
    [...]
}
catch (System.Exception exception)
{
   [...]
   throw;
}

Если бы я явно перехватывал System.Data.SqlClient.SqlException, я мог бы оценить ErrorNumber следующим образом.

try
{
  //insertion code
}
catch(SqlException ex)
{
  if(ex.Number == 2627)
  {
     //Violation of primary key. Handle Exception
  }
}

ErrorNumber 2627 в контексте SqlException означает нарушение уникального ключа. См. https://msdn.microsoft.com/en-us/library/ms151757%28v=sql.110%29.aspx

Все идет нормально. Поскольку я работаю с DbCommand и, следовательно, с различными типами систем управления реляционными базами данных, я ищу более общий способ уловить такое нарушение ограничения уникального ключа.

Спасибо за помощь.

3 ответа

Решение

Боюсь, для этого нет встроенного универсального решения. В качестве обходного пути вы можете создать оболочку для Execute...:

public static int ExecuteWithNiceExceptions(this IDbCommand cmd)
{
    try
    {
        return cmd.ExecuteNonQuery();
    }
    catch(SqlException ex)
    {
        if (ex.Number == 2627)
        {
            throw new PrimaryKeyViolationException(cmd, ex);
        }
        else
        {
            throw;
        }
    }
    catch (OleDbException ex)
    {
        ... 
    }
    ...
}

Таким образом, вы "конвертируете" различные специфичные для реализации исключения в общие значимые исключения.

Либо вы должны позволить базе данных назначить ключ или использовать GUID в качестве ключа, так как база данных предназначена для многопользовательского одновременного доступа, ваш код не может знать, каким должен быть следующий ключ, поэтому вам нужно либо разрешить БД управляйте своими собственными ключами или используйте ключ, который имеет гарантированную уникальность.

тем не менее, поскольку каждая реализация базы данных использует свой собственный набор кодов ошибок, нет никакого способа дать коды ошибок, не зная, какого поставщика вы используете, за исключением того, что они подали петицию в ISO для создания международного стандарта кодов ошибок, в чем я сомневаюсь буду работать

Я знаю, что вопрос касается ADO.NET, но если вы используете EF Core и вам нужен универсальный способ перехвата исключений базы данных, который также поддерживает все основные системы баз данных, проверьте EntityFramework.Exceptions .

Другие вопросы по тегам