Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 25.09.23 08:58
Оценка:
Добрый день!

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

Однако, за это время эту Сущность уже могли отредактировать в БД другие пользователи.
То есть наш пользователь видит неактуальные данные, и принимает решение о редактировании и записи Сущности на основе неактуальных данных.

Как должна делать программа в таких случаях?

Должна ли программа оповещать пользователя при изменении данных Сущности в БД?
Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

Объясните, пожалуйста.
Re: Проверка актуальности Entity перед записью
От: · Великобритания  
Дата: 25.09.23 09:39
Оценка: +1
Здравствуйте, zelenprog, Вы писали:


Z>Как должна делать программа в таких случаях?

Разрешать конфликт — как зависит от бизнес-требований. В простейшем случае отменять изменения пользователя и просить сделать ещё раз.

Z>Должна ли программа оповещать пользователя при изменении данных Сущности в БД?

Зависит от бизнес-требований

Z>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

Да, притом с ACID.

Z>Объясните, пожалуйста.

https://en.wikipedia.org/wiki/Optimistic_concurrency_control
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 25.09.2023 9:46 · . Предыдущая версия .
Re: Проверка актуальности Entity перед записью
От: bnk СССР http://unmanagedvisio.com/
Дата: 25.09.23 09:44
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Объясните, пожалуйста.


Это не забота программы, она все равно это не сможет реализовать это со 100% надежностью.
Это забота базы данных. Забота программы — выбрать подходящую стратегию блокирования (optimistic, pessimistic, etc)

Т.е. в идеале эту ситуацию должна ловить база, а в программе просто будет валиться ошибка в случае если текущий пользователь пытается перезаписать данные другого пользователя.
Ситуация которую ты описал, это в чистом виде перезаписывание данных введенных другим пользователем.
Отредактировано 25.09.2023 10:04 bnk . Предыдущая версия . Еще …
Отредактировано 25.09.2023 10:02 bnk . Предыдущая версия .
Отредактировано 25.09.2023 10:00 bnk . Предыдущая версия .
Re: Проверка актуальности Entity перед записью
От: Dym On Россия  
Дата: 25.09.23 09:45
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Должна ли программа оповещать пользователя при изменении данных Сущности в БД?

Да

Z>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

Да

Z>Объясните, пожалуйста.

Обычно выдается сообщение типа: "Данные, которые вы отредактировали изменены другим пользователем."

Второй вариант: блокировать на уровне субд типа "select for update", тогда пока первый не откоммитится, никто больше изменить данные не сможет.
Счастье — это Glück!
Re: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 27.09.23 12:09
Оценка:
Z>>Как должна делать программа в таких случаях?
·>Разрешать конфликт — как зависит от бизнес-требований. В простейшем случае отменять изменения пользователя и просить сделать ещё раз.

Z>>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

·>Да, притом с ACID.

Z>>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

DO>Да
DO>Обычно выдается сообщение типа: "Данные, которые вы отредактировали изменены другим пользователем."

Суть понял.

Поясните, пожалуйста, чуть подробнее как надо сделать в следующей ситуации.

1) Читаем из базы данных таблицу товаров.
Эта таблица (назовем ее "исходная") хранится в оперативной памяти (в качестве хеша) для более комфортной работы пользователя.
2) Для отображения пользователю, все строки этой таблицы копируются в новую таблицу, но колонки копируются не все.
Некоторые поля в новой таблице форматируются. И новая таблица отображается на форме пользователю. Это "пользовательская" таблица.
Соответствие между "исходной" и "пользовательской" таблицами один-к-одному по специальному ключу.
3) Пользователь просматривает свою таблицу товаров и корректирует в ней значения.
При корректировке для валидации используется "оригинальная" таблица, так как она содержит полную информацию по товару:
— программа находит строку "исходной" таблицы, соответствующую текущей строке "пользовательской" таблицы
— проверять корректность и допустимость изменений
4) Пользователь нажимает "Записать изменения".

Что должна сделать программа перед записью для проверки актуальности отредактированных сведений?

Правильно ли я понял, что программа должна сделать следующее:
1) по каждой отредактированной строке программа читает свежие данные из базы
2) сравнивает свежие данные с данными в строке "оригинальной" таблицы
3) если данные отличаются — выдается ошибка, процесс прерывается
4) если данные совпадают — записываем указанные пользователем сведения
5) строку "оригинальной" таблицы заполняем новыми сведениями, которые были только что записаны

Верно?
Отредактировано 27.09.2023 12:13 zelenprog . Предыдущая версия . Еще …
Отредактировано 27.09.2023 12:11 zelenprog . Предыдущая версия .
Re[2]: Проверка актуальности Entity перед записью
От: Dym On Россия  
Дата: 27.09.23 12:23
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Что должна сделать программа перед записью для проверки актуальности отредактированных сведений?

Z>Правильно ли я понял, что программа должна сделать следующее:
Z>1) по каждой отредактированной строке программа читает свежие данные из базы
Z>2) сравнивает свежие данные с данными в строке "оригинальной" таблицы
Z>3) если данные отличаются — выдается ошибка, процесс прерывается
Z>4) если данные совпадают — записываем указанные пользователем сведения
Z>5) строку "оригинальной" таблицы заполняем новыми сведениями, которые были только что записаны
Z>Верно?

Есть три версии записи:
1. В БД, назовем ее ACTUAL
2. Запрошенная пользователем, назовем ее OLD
3. Измененная пользователем, назовем ее NEW

Сравнивать нужно ACTUAL с OLD, если они не равны, значит кто-то уже успел откоммитится первым и изменять запись (накатывать NEW на ACTUAL) нельзя, об этом нужно сообщить пользователю.
Счастье — это Glück!
Re[3]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 27.09.23 13:38
Оценка:
DO>Есть три версии записи:
DO>1. В БД, назовем ее ACTUAL
DO>2. Запрошенная пользователем, назовем ее OLD
DO>3. Измененная пользователем, назовем ее NEW
DO>Сравнивать нужно ACTUAL с OLD, если они не равны, значит кто-то уже успел откоммитится первым и изменять запись (накатывать NEW на ACTUAL) нельзя, об этом нужно сообщить пользователю.

Это я понял.

Теперь меня интересует чуть более подробный алгоритм этих действий.

Тот алгоритм, который я описал — правильный?
Вот еще раз напишу.

Есть таблица товаров, прочитанная из БД. Есть копия этой таблицы, которая отображается пользователю на форме, которую он редактирует.
То есть имеем: "оригинальная" таблица, и "пользовательская" редактируемая таблица на форме.
Пользователь отредактировал какие-то записи и какие-то поля в таблице, нажимает "Записать".
Программа должна сделать следующие действия для каждой измененной записи таблицы:
1) прочитать свежие ACTUAL данные из базы
2) сравнить свежие данные с OLD данными в строке "оригинальной" таблицы
3) если данные отличаются — выдать ошибку, процесс прерывается
4) если данные совпадают — записать указанные пользователем сведения
5) строку "оригинальной" таблицы заполнить новыми сведениями, которые были только что записаны

Все правильно?

Обращаю внимание на пункт (5). "Оригинальную" таблицу нужно же обновить?
Верно?
Re[4]: Проверка актуальности Entity перед записью
От: Dym On Россия  
Дата: 27.09.23 13:45
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Обращаю внимание на пункт (5). "Оригинальную" таблицу нужно же обновить?

Зачем? Если ACTUAL = OLD, просто накатываются изменения в БД, и делается запрос актуальных данных из БД.
Счастье — это Glück!
Re[5]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 27.09.23 14:28
Оценка:
Z>>Обращаю внимание на пункт (5). "Оригинальную" таблицу нужно же обновить?

DO>Зачем?


Как зачем? Пользователь ведь дальше будет продолжать работать с программой.
А наша "оригинальная" таблица после записи содержит сведения, которые были прочитаны из базы в самом начале.
Значит, каждую запись, записанную в БД, надо обновить и в "оригинальной" таблице. Она же нам и в следующий раз будет нужна, чтобы сравнить актуальные данные с прочитанными ранее.

DO>Зачем? Если ACTUAL = OLD, просто накатываются изменения в БД, и делается запрос актуальных данных из БД.


"и делается запрос актуальных данных из БД" — а запрос каких данных? Всех?
Зачем из базы читать все данные, если например пользователь отредактировал и записал всего две записи?
Re[6]: Проверка актуальности Entity перед записью
От: samius Япония http://sams-tricks.blogspot.com
Дата: 27.09.23 15:12
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>"и делается запрос актуальных данных из БД" — а запрос каких данных? Всех?

— А потом вас там публично выпорют как бродяг и отправят в Сибирь убирать снег!
— Весь?
— Да
(Навеяло)
Re: Проверка актуальности Entity перед записью
От: gyraboo  
Дата: 27.09.23 15:16
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Объясните, пожалуйста.


В ынтерпрайзе есть 2 классических стратегии решения данной задачи, стандартной для ынтрпрайза:
— оптимистичная блокировка
— пессимистичная блокировка

Вообще кури ынтрпрайз (например, учебник гонзалвеса "изучаем jee"), там многие типовые задачи имеют стандартные проработанные решения на уровне спецификаций, чтоб ты свои кривые велосипеды не изобретал. А фреймворки типа Spring вообще имеют спектр модулей ещё шире чем кондовый ынтрпрайз, так что Spring тоже учить надо. Для расширения сознания без веществ ещё рекомендую книгу "jpa api и hibernate"
Отредактировано 27.09.2023 15:20 gyraboo . Предыдущая версия . Еще …
Отредактировано 27.09.2023 15:17 gyraboo . Предыдущая версия .
Re: Проверка актуальности Entity перед записью
От: Разраб  
Дата: 28.09.23 04:22
Оценка:
Здравствуйте, zelenprog, Вы писали:


версионирование записей БД. специальное поле которое увеличевается на 1 при обновлении.
Если при записи у вас версия меньше,значит кто-то уже успел изменить данные.
Дальше уже по желанию. тупо перезаписать. построить диалог с пользователем.
И да, вроде как подобный механизм есть в самих СУБД Multi version concurrency. Это надо по докам смотреть.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[2]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 28.09.23 06:00
Оценка:
Р>версионирование записей БД. специальное поле которое увеличевается на 1 при обновлении.
Р>Если при записи у вас версия меньше,значит кто-то уже успел изменить данные.
Р>И да, вроде как подобный механизм есть в самих СУБД Multi version concurrency. Это надо по докам смотреть.

В нашей платформе похоже нету такого механизма.
И изменить БД, чтобы добавить это специальное поле, я не могу.

Как быть?
Придется перечитывать запись перед записью и в "лоб" сравнивать старые и новые значения?
Re: Проверка актуальности Entity перед записью
От: vsb Казахстан  
Дата: 28.09.23 06:19
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Как должна делать программа в таких случаях?


Должна делать так, как аналитик или менеджер скажет. А ты, как программист, должен донести до него цену разных вариантов.

Из моего опыта (цифры условны):

В 80% случаев перезаписывать — приемлемо, т.к. пользователи обычно не работают над редактированием одного и того же.

В 10% случаев перезаписывать с сохранением истории.

В 9% случаев достаточно оптимистичной блокировки. Если при записи версия изменилась, то выдавать ошибку и пусть сам разбирается дальше.

В 1% делать какой-то коллаборативный редактор, автоматическое или полуавтоматическое разрешение конфликтов и прочую муть.
Re: Проверка актуальности Entity перед записью
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.09.23 06:19
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Как должна делать программа в таких случаях?


Z>Должна ли программа оповещать пользователя при изменении данных Сущности в БД?

Z>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

Z>Объясните, пожалуйста.

Это зависит прежде всего от того, для чего пишется программа, какие требования к ней выставляются. Легко представить программы, которые должны вести себя в таких ситуациях по-разному. И даже в по-разному в рамках одной и той же программы, например, в зависимости от типа редактируемой сущности, или от прав пользователя. То же касается и вопроса о том, нужно ли сверять всю таблицу, или отдельные записи (каждую отдельно или группами по неким признакам).
Re[3]: Проверка актуальности Entity перед записью
От: Буравчик Россия  
Дата: 28.09.23 07:21
Оценка: 9 (1)
Здравствуйте, zelenprog, Вы писали:

Z>Как быть?

Z>Придется перечитывать запись перед записью и в "лоб" сравнивать старые и новые значения?

Да, перечитывать запись придется. Но сравнение можно упростить — вычислять и сравнивать хэш от строки таблицы. Хранить хэши не нужно.

Когда клиент читает данные: вычисляем хэш от строчки в БД и передаем его клиенту.

Когда клиент записывает данные: клиент передает изменения строчки, а также передает имеющийся у него хэш.
Снова вычисляем хэш от имеющейся строчки в БД, и сравниваем с клиентским.
Если хэши совпали, то данные можно записывать. Если не совпали, значит кем-то были изменены.
Best regards, Буравчик
Re[3]: Проверка актуальности Entity перед записью
От: Разраб  
Дата: 28.09.23 07:31
Оценка:
Здравствуйте, zelenprog, Вы писали:


Р>>версионирование записей БД. специальное поле которое увеличевается на 1 при обновлении.

Р>>Если при записи у вас версия меньше,значит кто-то уже успел изменить данные.
Р>>И да, вроде как подобный механизм есть в самих СУБД Multi version concurrency. Это надо по докам смотреть.

Z>В нашей платформе похоже нету такого механизма.

Z>И изменить БД, чтобы добавить это специальное поле, я не могу.

Z>Как быть?

Z>Придется перечитывать запись перед записью и в "лоб" сравнивать старые и новые значения?
если нужно, от требовании исходим
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[7]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 28.09.23 07:39
Оценка:
Z>>"и делается запрос актуальных данных из БД" — а запрос каких данных? Всех?
S>- А потом вас там публично выпорют как бродяг и отправят в Сибирь убирать снег!
S>- Весь?
S>- Да
S>(Навеяло)

А если серьезно?
Re[4]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 28.09.23 07:49
Оценка:
Б>Да, перечитывать запись придется. Но сравнение можно упростить — вычислять и сравнивать хэш от строки таблицы. Хранить хэши не нужно.
Б>Когда клиент читает данные: вычисляем хэш от строчки в БД и передаем его клиенту.

Б>Когда клиент записывает данные: клиент передает изменения строчки, а также передает имеющийся у него хэш.

Б>Снова вычисляем хэш от имеющейся строчки в БД, и сравниваем с клиентским.
Б>Если хэши совпали, то данные можно записывать. Если не совпали, значит кем-то были изменены.

Понятно, спасибо!

А что надо сделать после того как в базу записаны новые данные?
В этот момент у нас есть две записи для этого товара:
— первая запись в "исходной" таблице, которая содержит старые значения реквизитов и хэш
— вторая запись в отредактированной пользователем "пользовательской" таблице на форме, значения реквизитов из этой таблицы (измененные пользователем) были записаны в базу

Ясно, что мы должны обновить запись и в "исходной" таблице.
Как это правильно сделать?

Варианта два:
1) Записать новые реквизиты из записи "пользовательской" таблицы в запись "исходной" таблицы
или
2) Перечитать из БД данные о товаре в "исходную" таблицу. А также в "пользовательскую" таблицу.
Вроде как этот вариант надежнее. Однако, он менее производительный, более трудоемкий.

Как лучше сделать?
Как это обычно делается на практике в реальных хороших программах?
Отредактировано 28.09.2023 7:51 zelenprog . Предыдущая версия . Еще …
Отредактировано 28.09.2023 7:50 zelenprog . Предыдущая версия .
Re[8]: Проверка актуальности Entity перед записью
От: Dym On Россия  
Дата: 28.09.23 07:53
Оценка: 6 (1)
Здравствуйте, zelenprog, Вы писали:

Z>А если серьезно?

Если серьезно, то ровне тем же запросом, каким вы получили данные из БД в "оригинальную" таблицу:

1) Читаем из базы данных таблицу товаров.

Вот это пункт.
Счастье — это Glück!
Re[8]: Проверка актуальности Entity перед записью
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.09.23 08:03
Оценка: 6 (1)
Здравствуйте, zelenprog, Вы писали:


Z>>>"и делается запрос актуальных данных из БД" — а запрос каких данных? Всех?

S>>- А потом вас там публично выпорют как бродяг и отправят в Сибирь убирать снег!
S>>- Весь?
S>>- Да
S>>(Навеяло)

Z>А если серьезно?

Серьезно невозможно ответить на этот вопрос, оперируя лишь понятием всех данных или нет. Несложно представить приложение, которое будет к редактированию данных относиться под девизом "все или ничего", когда вся совокупность данных воспринимается как единый документ, который должен быть непротиворечивым и потеря данных, внесенных другими пользователями, через перезапись должна быть исключена.
Опять, таки, это могут быть и не все-все данные, а все данные, касаемые какого-то одного заказа/проекта (например). Но ведь легче-то от этого не будет. Если схема данных не предусматривает версионирование изменений сущностей и редактирование отдельных строк должно быть исключено, то придется сравнивать именно теми сущностями, целостность которых требуется гарантировать.
Re[9]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 28.09.23 08:35
Оценка:
S>Серьезно невозможно ответить на этот вопрос, оперируя лишь понятием всех данных или нет. Несложно представить приложение, которое будет к редактированию данных относиться под девизом "все или ничего", когда вся совокупность данных воспринимается как единый документ, который должен быть непротиворечивым и потеря данных, внесенных другими пользователями, через перезапись должна быть исключена.
S>Опять, таки, это могут быть и не все-все данные, а все данные, касаемые какого-то одного заказа/проекта (например). Но ведь легче-то от этого не будет. Если схема данных не предусматривает версионирование изменений сущностей и редактирование отдельных строк должно быть исключено, то придется сравнивать именно теми сущностями, целостность которых требуется гарантировать.

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

У меня сначала была мысль просто скопировать новые реквизиты, указанные пользователем в "исходную" таблицу.
Но теперь я понимаю, что это неверный способ. Верно?
Re[10]: Проверка актуальности Entity перед записью
От: · Великобритания  
Дата: 28.09.23 08:57
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>У меня сначала была мысль просто скопировать новые реквизиты, указанные пользователем в "исходную" таблицу.

Z>Но теперь я понимаю, что это неверный способ. Верно?
Основная идея — тебе нужна атомарная compare-and-set операция.
Классика "update field1=:v1, field2=:v2, version = version + 1 where id=:id and version=:version" — потом вернуть и проверить что updated rows count > 0.
Если версий нет, то надо сравнивать сами значения "update Tbl set field1=:v1, field2=:v2 where id=:id and field1=:oldv1 and field2=:oldv2".
Если updated rows count нет, то надо использовать транзакцию с блокировкой: "begin transaction; select field1, field2 for update from Tbl where id = :id", compare resultset with old values, "update Tbl set field1=:v1, field2=:v2 where id=:id; commit"
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[10]: Проверка актуальности Entity перед записью
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.09.23 09:03
Оценка:
Здравствуйте, zelenprog, Вы писали:

S>>Серьезно невозможно ответить на этот вопрос, оперируя лишь понятием всех данных или нет. Несложно представить приложение, которое будет к редактированию данных относиться под девизом "все или ничего", когда вся совокупность данных воспринимается как единый документ, который должен быть непротиворечивым и потеря данных, внесенных другими пользователями, через перезапись должна быть исключена.

S>>Опять, таки, это могут быть и не все-все данные, а все данные, касаемые какого-то одного заказа/проекта (например). Но ведь легче-то от этого не будет. Если схема данных не предусматривает версионирование изменений сущностей и редактирование отдельных строк должно быть исключено, то придется сравнивать именно теми сущностями, целостность которых требуется гарантировать.

Z>Идею понял.

Z>После записи новых значений, надо перечитать из базы всю "порцию" данных, которая затронута записанными изменениями и которая представляют собой некую целостность.
Если пользователю нужно показать какую-то сумму заказа по позициям, то разумеется, но речь-то была не об этом, а о том, следует ли пытаться определить факт редактирования данных заказа другим пользователем при попытке текущего записать свою версию в базу. Уже тут могут быть варианты. Т.е. позиция в заказе может быть как самостоятельной единицей для редактирования, так и не быть самостоятельной единицей редактирования, если нам требуется (вдруг) гарантировать, что сумма позиций по заказу не должна превысить некий порок вообще никогда, т.е. в базу не должны попасть записи, которые в моменте переведут сумму заказа в недопустимое значение. Просто выдумываю для примера, что бы показать, что так может быть, но тем не менее, это не единственный способ реализации.

Z>У меня сначала была мысль просто скопировать новые реквизиты, указанные пользователем в "исходную" таблицу.

Z>Но теперь я понимаю, что это неверный способ. Верно?
Я немножко не понимаю, что такое новые реквизиты, исходная таблица, что является верным способом и какая вообще постановка задачи. Все рассуждения без этих данных — они могут быть только всего лишь о том, как решают схожие проблемы обычно, какие сценарии могут быть не очень обычные и т.п.
Ну вот как если бы хирург на практике позвонил бы сенсею и спросил бы, как правильно ампутировать руку, по кисть, по локоть, или по плечо? А тот бы ему ответил, что по плечо — ну это обычно помогает, и надежно. А с чем обратился пациент — да кому это надо?
Re[11]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 28.09.23 11:06
Оценка:
S>Я немножко не понимаю, что такое новые реквизиты, исходная таблица, что является верным способом и какая вообще постановка задачи. Все рассуждения без этих данных — они могут быть только всего лишь о том, как решают схожие проблемы обычно, какие сценарии могут быть не очень обычные и т.п.

Вот краткое пояснение:

1) Читаем из базы данных таблицу товаров.
Эта таблица (назовем ее "исходная") хранится в оперативной памяти (в качестве хеша) для более комфортной работы пользователя.
2) Для отображения пользователю, все строки этой таблицы копируются в новую таблицу, но колонки копируются не все.
Некоторые поля в новой таблице форматируются. И новая таблица отображается на форме пользователю. Это "пользовательская" таблица.
Соответствие между "исходной" и "пользовательской" таблицами один-к-одному по специальному ключу.
3) Пользователь просматривает свою таблицу товаров и корректирует в ней значения.
При корректировке для валидации используется "оригинальная" таблица, так как она содержит полную информацию по товару:
— программа находит строку "исходной" таблицы, соответствующую текущей строке "пользовательской" таблицы
— проверять корректность и допустимость изменений
4) Пользователь нажимает "Записать изменения".

И вопрос был про способ обновления таблиц товаров (и исходной, и пользовательской) после записи в базу.
Re[12]: Проверка актуальности Entity перед записью
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.09.23 12:12
Оценка: 6 (1)
Здравствуйте, zelenprog, Вы писали:

S>>Я немножко не понимаю, что такое новые реквизиты, исходная таблица, что является верным способом и какая вообще постановка задачи. Все рассуждения без этих данных — они могут быть только всего лишь о том, как решают схожие проблемы обычно, какие сценарии могут быть не очень обычные и т.п.


Z>Вот краткое пояснение:


Z>1) Читаем из базы данных таблицу товаров.

Z> Эта таблица (назовем ее "исходная") хранится в оперативной памяти (в качестве хеша) для более комфортной работы пользователя.
Кэш. Хэш — это другое. Хэш — это функция, отображающая данные на конечное множество.

Z>2) Для отображения пользователю, все строки этой таблицы копируются в новую таблицу, но колонки копируются не все.

Z> Некоторые поля в новой таблице форматируются. И новая таблица отображается на форме пользователю. Это "пользовательская" таблица.
Z> Соответствие между "исходной" и "пользовательской" таблицами один-к-одному по специальному ключу.
Z>3) Пользователь просматривает свою таблицу товаров и корректирует в ней значения.
Z>При корректировке для валидации используется "оригинальная" таблица, так как она содержит полную информацию по товару:
Z>— программа находит строку "исходной" таблицы, соответствующую текущей строке "пользовательской" таблицы
Z>— проверять корректность и допустимость изменений
Z>4) Пользователь нажимает "Записать изменения".

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

Z>И вопрос был про способ обновления таблиц товаров (и исходной, и пользовательской) после записи в базу.

А в теме "Проверка актуальности Entity перед записью".
Способ обновления тоже зависит от сценариев конкурентной работы. Если кроме пользователя никто записать данные не может, то в таблице будет то, что записал пользователь и смысла читать данные после записи как бы нет. Если набор редактируемых разными пользователями записей может пересекаться, то могут быть сценарии редактирования разных записей. И нам надо понять, не ломает ли это бизнес-процессы. Если нет, то проверять можно лишь измененные записи, а потом перечитывать все доступные пользователю. Если такой подход что-то портит, то надо исключать одновременные попытки редактирования даже разных записей и проверять весь набор доступных пользователю записей на то, что их никто не поменял. И тогда, после успешной записи нам опять нет необходимости перечитывать данные, т.к. там будет именно то, что записал пользователь только что.
Re[13]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 28.09.23 12:35
Оценка:
S>Все еще не ясны сценарии конкурентной работы с данными. Кем может быть нарушена актуальность Entity? Если таких сценариев не предполагается, то проверка слегка избыточна.
...
S>Способ обновления тоже зависит от сценариев конкурентной работы. Если кроме пользователя никто записать данные не может, то в таблице будет то, что записал пользователь и смысла читать данные после записи как бы нет.

База данных является многопользовательской.
Одновременно могут работать несколько пользователей, и добавлять товары из старых источников в новую базу.
Одному новому товару в новой базе может соответствовать несколько товаров из старых баз: из одной старой базы для нового товара подгрузили значения в "поле-1" и "поле-2", из другой старой базы подгрузили "поле-3" и "поле-4".

Z>>И вопрос был про способ обновления таблиц товаров (и исходной, и пользовательской) после записи в базу.

S>А в теме "Проверка актуальности Entity перед записью".

Я не точно выразился.
Я имел ввиду: "и у меня был еще один вопрос про способ обновления таблиц товаров ...".

S>Если набор редактируемых разными пользователями записей может пересекаться ...

S>И нам надо понять, не ломает ли это бизнес-процессы.

Вроде бы не ломает.

S>Если нет, то проверять можно лишь измененные записи, а потом перечитывать все доступные пользователю.


Получается, мы должны после записи по сути заново перестроить все кеши: и таблицу "исходную" и таблицу "пользовательскую".
Или по крайней мере, перечитать из базы и обновить в этих кешах те записи, которые были отредактированы пользователем.
Верно?
Re[14]: Проверка актуальности Entity перед записью
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.09.23 14:30
Оценка: 6 (1)
Здравствуйте, zelenprog, Вы писали:


S>>Все еще не ясны сценарии конкурентной работы с данными. Кем может быть нарушена актуальность Entity? Если таких сценариев не предполагается, то проверка слегка избыточна.

Z>...
S>>Способ обновления тоже зависит от сценариев конкурентной работы. Если кроме пользователя никто записать данные не может, то в таблице будет то, что записал пользователь и смысла читать данные после записи как бы нет.

Z>База данных является многопользовательской.

Z>Одновременно могут работать несколько пользователей, и добавлять товары из старых источников в новую базу.
Z>Одному новому товару в новой базе может соответствовать несколько товаров из старых баз: из одной старой базы для нового товара подгрузили значения в "поле-1" и "поле-2", из другой старой базы подгрузили "поле-3" и "поле-4".

Примерно понятно

Z>Получается, мы должны после записи по сути заново перестроить все кеши: и таблицу "исходную" и таблицу "пользовательскую".

Ну кэши хочется держать актуальными до некоторой степени.

Z>Или по крайней мере, перечитать из базы и обновить в этих кешах те записи, которые были отредактированы пользователем.

Те, которые редактировал пользователь и известно, что они прижились в базе, эти изменения можно и самому внести в кэши. Проблема будет с теми записями, которые обновлял другой пользователь.
Поэтому, перечитывать все — может быть хорошим решением.
Z>Верно?
Это на экзамене есть верный ответ, а есть верный ответ с точки зрения преподавателя/составителя вопросов. В программировании есть подходы, которые в разной степени чем-то лучше, чем-то хуже, часто выбор между ними не очевиден.
Вместо перечитывания всех таблиц для обновления локального кэша можно, например, запрашивать изменения, которые будут записываться в специальную таблицу(не обязательно таблицу)/журнал изменений. И из них читать лишь те, которые касаются конкретного пользователя. Решение позамороченнее, но больше подходит для большого числа пользователей и редактируемых записей. А может оно и не окупится, если пользователей 5, а товаров 500.
Не настаиваю на правильности того или другого решения, просто показываю, что они есть, аргументировать можно и то и другое, контраргументировать — тоже, а все оценки до реализации конкретного подхода делаются пальцем в носу.
Re: Проверка актуальности Entity перед записью
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 28.09.23 22:29
Оценка: 6 (1)
Здравствуйте, zelenprog, Вы писали:


Z>Добрый день!


Z>Программа прочитала из базы данных некую сущность Entity, и показала ее пользователю для редактирования.

Z>Пользователь долго думает, изменяет ее свойства и нажимает кнопку "Записать".
Z>Однако, за это время эту Сущность уже могли отредактировать в БД другие пользователи.
Z>То есть наш пользователь видит неактуальные данные, и принимает решение о редактировании и записи Сущности на основе неактуальных данных.

Z>Как должна делать программа в таких случаях?


Z>Должна ли программа оповещать пользователя при изменении данных Сущности в БД?

Z>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

В момент сохранения данных запрос должен проверять сохраненную версию строки в базе и значение этой версии в скрытом поле формы. В базах данных есть rowversion и аналоги для этого, версию строки можно поменять на ручное сравнение со старыми значениями в коде запроса. В HTTP есть заголовки lastmodified и etag, а также if-modified-since\if-match. Этот механизм нужно обязательно, чтобы защититься от потерянных изменений данных.

Следующие возможности уже опциональны и зависит от того, какой пользовательский опыт вы хотите дать:
1) Если в момент сохранения становится известно что версия строки изменилась за время работы пользователя, то нужно получить новую версию с сервера и попытаться смержить данные, введенные пользователем, и данные из базы. Дальше уже пользователь примет решение надо ли сохранять.
2) Можно прикрутить веб-сокерты и\или rabbitmq чтобы пушить пользователю информацию, что запись изменилась до того, как он нажмет "сохранить"
Re: Проверка актуальности Entity перед записью
От: IT Россия linq2db.com
Дата: 07.10.23 21:25
Оценка: 30 (2) +1
Здравствуйте, zelenprog, Вы писали:

Z>Объясните, пожалуйста.


Что-то вы тут долго мусолите простейшую задачу.

Сохранение следует делать следующим образом:

UPDATE Table
SET
    Column1 = @newValue1,
    Column2 = @newValue2,
    VersionColumn = SqlGeneratedValue -- или default value
WHERE
    EntityID = @id AND VersionColumn = @entityVersion


В ADO.NET Execute медоты возвращают в качестве результата значение Affected Rows. Если это значение равно 0, то кто-то уже обновил запись. Сообщаем пользователю, дальше по вкусу.

В результате не требуется никаких транзакций, дополнительных чтений и пр.
Если нам не помогут, то мы тоже никого не пощадим.
Отредактировано 07.10.2023 21:27 IT . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.