Как я могу игнорировать исключение DbUpdateConcurrencyException с моим кодом Entity Framework?

Есть ли способ, которым я могу сказать EF, чтобы не беспокоиться о количестве строк a DELETE или UPDATE делать или не делать?

Я пытаюсь удалить строку из базы данных, но из-за того, что строка не существует, EF генерирует исключение: DbUpdateConcurrencyException.. говоря, что были затронуты 0 строк. Это правильно → ни одна строка не была удалена. Но это совершенно нормально.. потому что нет данных.

Я действительно не хочу совершать кругосветное путешествие к БД, чтобы увидеть, существует ли эта строка.. и если да, тогда попробуйте и удалите ее.

Если я попытаюсь усвоить исключение в блоке try / catch, тогда остальные элементы, которые нужно удалить, НЕ отправляются в db, когда я пытаюсь SaveChanges()... что плохо.

например.

Delete(new Foo(1));
Delete(new Foo(2));
Delete(new Foo(3));
SaveChanges(); // <-- Throws the exception.

// DB Trace : DELETE FROM Foo WHERE Id = 1;

и т.д. там нет трассы, показывающей запись 2 или 3, пытающуюся удалить... поскольку исключение останавливает все: (

Любые идеи?

UPDATE

Как работает DELETE? Здесь код... (упрощенный и строго типизированный)

public void Delete(Foo foo)
{
    if (foo == null)
    {
        throw new ArgumentNullException("foo");
    }

    Foo attachedEntity = Context.Set<Foo>().Local.FirstOrDefault(x => x.Id > 0);

    if (attachedEntity != null)
    {
        // Entity already in object graph - remove entity.
        Context.Set<Foo>().Remove(attachedEntity);
    }
    else
    {
        // Entity not in object graph, attach and set EntityState to Deleted.
        Context.Entry(foo).State = EntityState.Deleted;
    }
}

Ответ 1

Я думаю, что поведение EF верное - просто вы должны выполнять команды только для объектов, которые присутствуют в БД. Это не для сценариев вроде: "Я попробую, и мы увидим...". Если вы не можете быть уверены, что объект существует в БД, и вы не хотите совершать поездку в оба конца (что, по моему мнению, является лучшей идеей, потому что удаление отдельного объекта может иметь несколько других ловушек, особенно если объект участвует в независимых ассоциациях), вы должны использовать DbContext.Database.SqlCommand и выполните процедуру хранения.

Ниже описывается правильный способ обработки DbUpdateConcurrencyException здесь = > После каждого исключения вы должны разрешать confilicts (в вашем случае это означает удаление проблемных объект из DbContext) и снова выполнить SaveChanges.

Ответ 2

Фактически вы можете игнорировать эти проблемы, установив:

db.Configuration.ValidateOnSaveEnabled = false;

Где db - это экземпляр DbContext.

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