отображение строчек таблицы базы в объекты?
От: dave_2  
Дата: 12.01.18 21:17
Оценка:
Возьмем для примера простейшую таблицу:

CREATE TABLE tbl(key INTEGER PRIMARY KEY, cap TEXT NOT NULL);


Если вставить новую запись с полем cap='AAA' (INSERT), удалить ее (DELETE)
и вставить новую (INSERT) с cap='BBB'.
То по крайней мере в sqlite запись с cap='AAA' и c cap='BBB'
будут иметь одинаковый "key" (имеется ввиду удаленная запись с cap='AAA'
имела скажем key=1, и новая запись тоже будет иметь key=1).

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

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

Что в таким случаях делают, вводят типа "кэш" между классами отвечающими
за работу с базой и программой, и все GUI работающее с базой подписываются
на события "кэша" и если в одном окне объект удаляется, то "кэш" извещает
окна что такого объекта нет?
Отредактировано 12.01.2018 21:18 dave_2 . Предыдущая версия .
Re: отображение строчек таблицы базы в объекты?
От: Qulac Россия  
Дата: 12.01.18 21:43
Оценка: 2 (1) +1
Здравствуйте, dave_2, Вы писали:

_>Возьмем для примера простейшую таблицу:


_>
_>CREATE TABLE tbl(key INTEGER PRIMARY KEY, cap TEXT NOT NULL);
_>


_>Если вставить новую запись с полем cap='AAA' (INSERT), удалить ее (DELETE)

_>и вставить новую (INSERT) с cap='BBB'.
_>То по крайней мере в sqlite запись с cap='AAA' и c cap='BBB'
_>будут иметь одинаковый "key" (имеется ввиду удаленная запись с cap='AAA'
_>имела скажем key=1, и новая запись тоже будет иметь key=1).

_>Я разрабатываю приложение, которое должно позволить

_>открывать одну и ту же запись в разных независимых окнах (вернее множество
_>записей пересечение которые может быть не нулевое, но для упрощение ограничимся
_>одной записью).

_>И вот допустим мы прочитали какую-то запись из таблицы,

_>превратили ее в объект,и открыли этот объект в нескольких окнах.
_>В одном окне мы нажали кнопку удалить, потом создали новую запись,
_>в это время у нас все еще открыто третье окно в котором данные уже
_>удаленной записи, допустим мы в нем что-то меняем и нажимаем сохранить,
_>и получится ерунда какая-то, если использовать "key" как уникальный
_>идентификатор объекта базы.

_>Что в таким случаях делают, вводят типа "кэш" между классами отвечающими

_>за работу с базой и программой, и все GUI работающее с базой подписываются
_>на события "кэша" и если в одном окне объект удаляется, то "кэш" извещает
_>окна что такого объекта нет?

С точки зрения бд тут всё ок — все сущности имеют уникальный первичный ключ. Проблема возникает от того, что клиенты работают с разными версиями данных. Решения: использовать транзакции, выбрать натуральный уникальный или первичный ключ, перенастроить что то в sqllite, что бы первичный ключ повторно не использовался бы.
Программа – это мысли спрессованные в код
Отредактировано 12.01.2018 21:46 Qulac . Предыдущая версия .
Re[2]: отображение строчек таблицы базы в объекты?
От: dave_2  
Дата: 12.01.18 22:21
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Здравствуйте, dave_2, Вы писали:


_>>Что в таким случаях делают, вводят типа "кэш" между классами отвечающими

_>>за работу с базой и программой, и все GUI работающее с базой подписываются
_>>на события "кэша" и если в одном окне объект удаляется, то "кэш" извещает
_>>окна что такого объекта нет?

Q>С точки зрения бд тут всё ок — все сущности имеют уникальный первичный ключ. Проблема возникает от того, что клиенты работают с разными версиями данных. Решения:


> использовать транзакции,


А как это поможет? В описанном мной сценарии будет вызваться "update" с валидным ключом,
другое дело что хотим обновить старую версию данных, а обновляем новую. То есть sql часть
отработает без вопросов и ошибок.

> выбрать натуральный уникальный или первичный ключ, перенастроить что то в sqllite, что бы первичный ключ повторно не использовался бы.


Можно выставить свойства первичного ключа AUTOINCREMENT, и тогда все будет хорошо,
но напрягает что когда дело дойдет до 2^64-1 больше запись объектов будет невозможна (ограничение sqlite).
По идее пользователь за 1000 лет до такого не дойдет, но напрягает.
Re[3]: отображение строчек таблицы базы в объекты?
От: Qulac Россия  
Дата: 12.01.18 22:32
Оценка: 2 (1)
Здравствуйте, dave_2, Вы писали:

_>Здравствуйте, Qulac, Вы писали:


Q>>Здравствуйте, dave_2, Вы писали:


_>>>Что в таким случаях делают, вводят типа "кэш" между классами отвечающими

_>>>за работу с базой и программой, и все GUI работающее с базой подписываются
_>>>на события "кэша" и если в одном окне объект удаляется, то "кэш" извещает
_>>>окна что такого объекта нет?

Q>>С точки зрения бд тут всё ок — все сущности имеют уникальный первичный ключ. Проблема возникает от того, что клиенты работают с разными версиями данных. Решения:


>> использовать транзакции,


_>А как это поможет? В описанном мной сценарии будет вызваться "update" с валидным ключом,

_>другое дело что хотим обновить старую версию данных, а обновляем новую. То есть sql часть
_>отработает без вопросов и ошибок.

Имелось в виду не давать нескольким пользователям изменять одни и те же данные или использовать оптимистическую блокировку.

>> выбрать натуральный уникальный или первичный ключ, перенастроить что то в sqllite, что бы первичный ключ повторно не использовался бы.


_>Можно выставить свойства первичного ключа AUTOINCREMENT, и тогда все будет хорошо,

_>но напрягает что когда дело дойдет до 2^64-1 больше запись объектов будет невозможна (ограничение sqlite).
_>По идее пользователь за 1000 лет до такого не дойдет, но напрягает.

А 10000 лет не будет напрягать?
Программа – это мысли спрессованные в код
Re: отображение строчек таблицы базы в объекты?
От: wildwind Россия  
Дата: 13.01.18 07:51
Оценка: 17 (2)
Здравствуйте, dave_2, Вы писали:

_>Что в таким случаях делают, вводят типа "кэш" между классами отвечающими

_>за работу с базой и программой, и все GUI работающее с базой подписываются
_>на события "кэша" и если в одном окне объект удаляется, то "кэш" извещает
_>окна что такого объекта нет?

Примерно так, только называется это не "кэш", а блокировки. При начале редактирования в форме происходит попытка заблокировать объект в БД. Если он уже заблокирован, пользователь получает сообщение об ошибке.

Это т.н. пессимистические блокировки. бывают еще оптимистические, но для простоты пока не будем о них.

SQLite не поддерживает блокировки на уровне отдельных строк, только таблицы целиком. Придется либо реализовать их в приложении, либо сменить СУБД.
Re[2]: отображение строчек таблицы базы в объекты?
От: dave_2  
Дата: 13.01.18 14:55
Оценка:
Здравствуйте, wildwind, Вы писали:


W>Примерно так, только называется это не "кэш", а блокировки. При начале редактирования в форме происходит попытка заблокировать объект в БД. Если он уже заблокирован, пользователь получает сообщение об ошибке.


W>Это т.н. пессимистические блокировки. бывают еще оптимистические, но для простоты пока не будем о них.


W>SQLite не поддерживает блокировки на уровне отдельных строк, только таблицы целиком. Придется либо реализовать их в приложении, либо сменить СУБД.


Допустим в sqlite были бы пессимистические блокировки на уровне рядов таблицы.
Понятно как это поможет в сценарии взяли объект, поменяли и возвращаем на то место откуда взяли.
Но как они помогут в согласованности данных в разных окнах?

Допустим есть окно со списком объектов, двойным кликом открывается окно просмотра
объекта, в котором есть кнопки "Удалить" и "Редактировать".
При нажатии "Редактировать" или "Удалить" логично взять блокировку,
но как другие "окна" которые работают с базой только на чтение получат
информацию о том что что-то поменялось и надо вытащить данные заново?

Понятно как это делать когда окна редактирования модальные, и после возвращения
управления можно перечитать базу, а если они как в моем случае немодальные?
Re[3]: отображение строчек таблицы базы в объекты?
От: wildwind Россия  
Дата: 13.01.18 15:54
Оценка:
Здравствуйте, dave_2, Вы писали:

_>Допустим в sqlite были бы пессимистические блокировки на уровне рядов таблицы.

_>Понятно как это поможет в сценарии взяли объект, поменяли и возвращаем на то место откуда взяли.
_>Но как они помогут в согласованности данных в разных окнах?

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

_>Допустим есть окно со списком объектов, двойным кликом открывается окно просмотра

_>объекта, в котором есть кнопки "Удалить" и "Редактировать".
_>При нажатии "Редактировать" или "Удалить" логично взять блокировку,
_>но как другие "окна" которые работают с базой только на чтение получат
_>информацию о том что что-то поменялось и надо вытащить данные заново?

Например, окна могут слать друг другу уведомления. Ну или главному окну, которое будет пересылать их всем остальным.

Кстати, блокировки бывают и на чтение тоже, так что можно использовать и их, если это не будет мешать другим пользователям.
Re: отображение строчек таблицы базы в объекты?
От: Vasiliy2  
Дата: 25.01.18 11:41
Оценка:
Здравствуйте, dave_2, Вы писали:

_>Возьмем для примера простейшую таблицу:


_>
_>CREATE TABLE tbl(key INTEGER PRIMARY KEY, cap TEXT NOT NULL);
_>


Самый простой способ — не использовать INTEGER. Использовать, например, guid.
хабр
Re: отображение строчек таблицы базы в объекты?
От: MozgC США http://nightcoder.livejournal.com
Дата: 25.01.18 14:58
Оценка:
Autoincrement + успокоительные, чтобы не париться зазря.

+ Оптимистическая блокировка, типа (упрощенно, чтобы был понятен смысл оптимистической блокировки):

public void UpdateRecord(Record r)
{
    int rowsUpdated = _db.Execute($"UPDATE records SET cap = 'blabla' WHEER Key = {r.Key} AND TimeStamp = '{r.TimeStamp}'"); // Вместо TimeStamp можно использовать int version

    if (rowsUpdated == 0) // запись не найдена
    {
        // тут решаем что делать, например выкидываем исключение или проверяем что запись с Key = 1 всё еще в базе, и тогда можно предложить пользователю перезаписать её.
    }
}
Отредактировано 25.01.2018 18:51 MozgC . Предыдущая версия .
Re[2]: отображение строчек таблицы базы в объекты?
От: MozgC США http://nightcoder.livejournal.com
Дата: 25.01.18 18:52
Оценка:
Здравствуйте, Vasiliy2, Вы писали:

V>Самый простой способ — не использовать INTEGER. Использовать, например, guid.

V> хабр

При использовании guid PK не забыть убедиться, что PK — non clustered.
Re: отображение строчек таблицы базы в объекты?
От: antropolog  
Дата: 27.01.18 19:26
Оценка:
Здравствуйте, dave_2, Вы писали:

_>Что в таким случаях делают, вводят типа "кэш" между классами отвечающими

_>за работу с базой и программой, и все GUI работающее с базой подписываются
_>на события "кэша" и если в одном окне объект удаляется, то "кэш" извещает
_>окна что такого объекта нет?

примерно так, только называют это не "кэш", а "модель". Все запросы в базу идут через модель, поэтому модель знает когда что-то поменялось в базе, и уведомляет об этом всех заинтересованных. В общем, вы близки к тому чтобы изобрести MVC.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.