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

У меня есть классы сущностей, которые имеют целочисленное свойство (названное ROW_VERSION) с ConcurrencyMode, установленным в "Fixed" для оптимистической проверки параллелизма. Я увеличиваю значение этого столбца в своем коде приложения перед сохранением сущности этого типа (поэтому для StoreGeneratedPattern задано значение None). Это хорошо работает при сохранении изменений.

Теперь я также хотел бы обнаружить ошибку параллелизма, когда у меня есть ранее загруженная сущность (с ROW_VERSION = x), и я создаю новый DbContext, присоединяю эту сущность и выдаю запрос, включающий эту сущность. Проблема в том, что если ROW_VERSION был увеличен другим клиентским приложением (ROW_VERSION = x + 1), это не обнаруживается во время моего запроса, потому что значение присоединенной сущности имеет очевидный приоритет (что полностью имеет смысл для общих значений столбца).

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

Я использую Entity Framework 4.3 с.NET 4.0.

Изменить (в ответ на комментарий от Герт Арнольд):

Я пытаюсь прояснить мою проблему немного больше...

Примечания о том, как работает мое приложение в целом:

  • Существует древовидное представление, показывающее мои доступные объекты сущностей, и при выборе одного из них полная сущность загружается из БД для отображения в подробном представлении, где ее можно редактировать.

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

  • DbContexts создаются отдельно для запросов и сохранения изменений (т. Е. У меня не всегда один и тот же DbContext, но они создаются по мере необходимости).

  • Когда объект-сущность загружается для отображения в подробном представлении, все ранее измененные объекты-сущности (которые кэшируются) присоединяются к DbContext, который сначала используется для запроса. Затем выдается фактический запрос. Поэтому, если я запрашиваю объект сущности, который был изменен до того, как я получу измененную версию как результат, а не версию из базы данных (которая могла бы измениться за это время).

Итак, вот пример, который показывает мою проблему:

  1. Клиентское приложение 1 загружает объект сущности с ROW_VERSION = 1, удаляет DbContext и сохраняет ссылку на этот объект сущности для дальнейшего редактирования.

  2. Клиентское приложение 2 загружает тот же объект сущности, который был упомянут на шаге 1, изменяет свойство и сохраняет изменения. Это приводит к увеличению ROW_VERSION в БД (сейчас 2).

  3. Пользователь клиентского приложения 1 теперь меняет некоторые свойства объекта-сущности (который все еще находится в памяти с ROW_VERSION, равным 1).

  4. Прежде чем клиентское приложение 1 сохраняет изменения, оно загружает некоторые другие объекты сущности для отображения и в конечном итоге снова выбирает рассматриваемый объект сущности (например, для просмотра внесенных изменений). Это вызывает запрос, в котором результат будет содержать уже измененный объектный объект (потому что он присоединен к DbContext до того, как фактический запрос будет отправлен в базу данных).

    И вот моя проблема: на этом этапе инфраструктура сущностей может сравнить ROW_VERSION присоединенного объекта с объектом этого объекта в фактическом результате запроса, обнаружить несоответствие и, например, выдать исключение.

    Но вместо этого EF обрабатывает свойство ROW_VERSION, как и все другие свойства, которые могли быть просто изменены клиентом.

Поэтому я хочу, чтобы EF специально обработал свойство ROW_VERSION и сравнивал его значения в каждом запросе для обнаружения изменений другими клиентами. Таким образом, я бы обнаружил ситуации параллелизма раньше, чем при ожидании вызова SaveChanges.

1 ответ

Решение

Я думаю, что теперь понимаю, но я не понимаю, как Entity Framework может помочь вам здесь.

  1. Оптимистичный параллелизм по определению - это стратегия обработки конфликтов при фиксации данных. Не при чтении данных. Так что это будет отходом от ожидаемого поведения, если ConcurrencyMode будет реализован таким образом (даже когда настраивается).
  2. Предположим, что классы сущностей EF могут быть настроены так, чтобы вести себя так при чтении Было бы очень трудно иметь дело со всеми возможными исключениями при получении списка этих объектов или графа объектов, содержащего эти объекты. Следует ли откатить все чтение? Так что это, вероятно, будет полезно только при чтении отдельных объектов. Это была бы очень (читай: слишком) детальная спецификация конфигурации.

Насколько я понимаю, если вы хотите эту систему раннего предупреждения, вам придется программировать ее самостоятельно. Это должно включать какой-то запрос, чтобы прочитать значение версии специально, потому что Refresh с StoreWins (ObjectContext) или Reload (DbContext) всегда перезаписывает все значения.

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