Поведение EF ObjectContext при ошибке SQL INSERT - PullRequest
0 голосов
/ 25 марта 2012

У меня есть этот простой кусок кода:

        MyObjectContext db = new MyObjectContext();

        Person new_person = new Person() {
           /* some data, which does not satisfy
           the constraints of unique key */
        };

        db.Person.AddObject(new_person);
        db.SaveChanges();

В таблице базы данных MSSQL у меня есть уникальный ключ в таблице Person. Когда я пытаюсь добавить объект new_person, который не может быть добавлен из-за уникальных ограничений, база данных возвращает ошибку, как и ожидалось, но в дальнейшей работе MyObjectContext действует, подобно этим вставкам было применено БД. Как будто не слышал ошибки. Только перезапуск приложения помогает обновить MyObjectContext актуальными данными.

Как получить ObjectContext, уведомленный об ошибке, возвращенной из базы данных, после попытки выполнить INSERT?




UPD: Спасибо за ваши ответы.

Когда я пытаюсь добавить объект с двойным уникальным ключом, я получаю это:

Server Error in '/' Application.
Violation of UNIQUE KEY constraint 'IX_Person'. Cannot insert duplicate key in object 'dbo.Person'.
The statement has been terminated.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.SqlClient.SqlException: Violation of UNIQUE KEY constraint 'IX_Person'. Cannot insert duplicate key in object 'dbo.Person'.
The statement has been terminated.

Source Error:

Line 34: 
Line 35:            db.Person.AddObject(new_person);
>Line 36:           db.SaveChanges();
Line 37: 
Line 38:            return Json(new ViewPerson(new_person));


Source File: C:\DEV\MyProject\Controllers\PersonController.cs    Line: 36

Stack Trace:

[SqlException (0x80131904): Violation of UNIQUE KEY constraint 'IX_Person'. Cannot insert duplicate key in object 'dbo.Person'.
The statement has been terminated.]
   System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +2073550
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +5064508
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +234
   System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +2275
   System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +33
   System.Data.SqlClient.SqlDataReader.get_MetaData() +86
   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +311
   System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +987
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +162
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
   System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141
   System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +12
   System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) +10
   System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary`2 identifierValues, List`1 generatedValues) +8167912
   System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) +267



После этого в следующем запросе к серверу я получаю исключение во второй строке этого кода:

Category some_category = MyEntitiesHelper.db.Category.Single(c => c.ID == 1);
Person some_person = some_category.Person.SingleOrDefault(p => p.UniqueID == "uniqueKey");

System.InvalidOperationException: {"Последовательность содержит более одного совпадающего элемента"}

Это произошло, потому что (я проверял во время сеанса отладки), в some_category.Person было был другой человек с дубликатом uniqueKey, которого не должно быть, потому что он не пошел в базу данных, потому что при вставке база данных вернула ошибку. Дублированный объект person имел ID = 0.



Кстати, объект ObjectContext создается так:

public static class MyEntitiesHelper
{

    private static MyObjectContext _db;
    public static MyObjectContext db
    {
        get
        {
            if (_db == null) _db = new MyObjectContext();
            return _db;
        }
    }


}

Новый экземпляр создается для каждого запроса, или это не так? Это хороший подход?



Вопрос остается тем же: как предотвратить исключение «Последовательность содержит более одного совпадающего элемента» при попытке

Person some_person = some_category.Person.SingleOrDefault(p => p.UniqueID == "uniqueKey");

Существует второй объект Person с дубликатом uniqueKey, прикрепленным к objectcontext, которого там быть не должно.

1 Ответ

1 голос
/ 25 марта 2012

Как вы можете сказать, что objectContext работает так, как будто все прошло нормально? Вы выполняете другой запрос или просто используете свойство навигации, которое использует этот новый объект Person? как

Person newPerson = someRelatedEntity.Persons.Where(p=>p.PersonID = "uniqueKey").FirstOrDefault();

Когда вы вызываете AddObject, вы, очевидно, присоединяете сущность к контексту, и она остается, даже если SaveChanges работает неправильно, но не может быть возможным, чтобы запрос в другой раз после этой базы данных мог бы извлечь этот новый объект.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...