Entity Framework: как правильно обрабатывать исключения, возникающие из-за ограничений SQL - PullRequest
17 голосов
/ 12 сентября 2010

Я использую Entity Framework для доступа к своим данным SQL.У меня есть некоторые ограничения в схеме базы данных, и мне интересно, как обрабатывать исключения, вызванные этими ограничениями.

В качестве примера я получаю следующее исключение в случае, когда два пользователя пытаются добавить (почти) идентичныесущность к БД одновременно.

System.Data.UpdateException
"An error occurred while updating the entries. See the InnerException for details."

(inner exception) System.Data.SqlClient.SqlException
"Violation of UNIQUE KEY constraint 'Unique_GiftId'. Cannot insert duplicate key in object 'dbo.Donations'.\r\nThe statement has been terminated."

Как правильно перехватить это конкретное исключение?

Грязное решение:

    catch (UpdateException ex)
    {
        SqlException innerException = ex.InnerException as SqlException;
        if (innerException != null && innerException.Message.StartsWith("Violation of UNIQUE KEY constraint 'Unique_GiftId'"))
        {
            // handle exception here..
        }
        else
        {
            throw;
        }
    }

Сейчасэтот подход работает, у него есть некоторые недостатки:

  • Отсутствие безопасности типов: код зависит от сообщения об исключении, которое содержит имя уникального столбца.
  • Зависимость от классов SqlCLient (сломанная абстракция)

Знаете ли вы лучшее решение для этого?Спасибо за все отзывы ..

Примечание: Я не хочу кодировать ограничения вручную на прикладном уровне, я хочу, чтобы они были в БД.

Ответы [ 3 ]

17 голосов
/ 12 сентября 2010

Вы должны быть в состоянии перехватить номер ошибки SQL (который является SqlException.Number )

В данном случае это 2627, что было всегда для SQL Server.

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

2 голосов
/ 12 сентября 2010

Один из способов - проверить свойство Errors внутреннего SqlException.Класс SqlError имеет свойство Number , которое идентифицирует точную ошибку.См. Таблицу всех кодов ошибок в таблице master.dbo.sysmessages.

Конечно, это все еще связывает вас с Sql Server.Я не знаю способа абстрагироваться от этого, кроме как использовать собственный анализатор исключений EF.

0 голосов
/ 10 мая 2012

Этот сценарий не должен происходить, так как ключ никогда не должен назначаться явно при использовании EF;скорее позволяя контексту назначать соответствующий.Если это проблема параллелизма, вам следует выполнить обновление в области транзакции.

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

...