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...
Пока на собственное сообщение не было ответов, его можно удалить.