Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Базы данных под .NET > Изменение данных в БД


Автор: eon 22.9.2010, 08:11
Здравствуйте!
Есть клиентская программа, которая ставится на несколько компьютеров. Каждый клиент работает с одной БД, которая находится на сервере MS SQL Server 2008. Приложение разрабатывал на VS2008. C#
Ситуация: при изменении (добавлении или удалении) записи в БД одним из клиентов, это изменение мгновенно должно отобразиться у всех клиентов в приложении в DataGrid.
На данном этапе сделал кнопкой Обновить, при нажатии на которую обновляется DataGrid. Но это ручной механизм. Охото автоматический.
Вообще это проблема широкого распространения. Книжек штук 10 перелистал, не нашел :(
Есть способы: по таймеру обновлять (например каждую минуту), но эт неочень хороший способ. Есть способ с помощью триггеров. На сколько я знаю, производительность системы падает. Но мне в принципе подойдет этот способ, думаю небольшая нагрузка на сервер будет у меня.
Есть еще способы, более современные. 
Подскажите что делать??
Если кто знает как сделать с помощью триггеров, напишите поподробнее, пожалуйста.
Спасибо.

Автор: MasterOfCode 22.9.2010, 08:41
Интересный вопрос. Может в отдельном потоке делать запрос к БД на наличие изменений в таблице и делать refresh на клиенте?

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

Автор: CYBERDREAM 22.9.2010, 09:09
Приветствую eon
Ну а если создать табличку нечто вроде:
TableName | Action | Date

и как только какой то пользователь сделал изменнеие в какой то таблице, он делает запись в выше указанной, мол изменял данные в таблице "Таблица продуктов" | "Добавление" | "2010.10.03 14:45:09"

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

Добавлено @ 09:13
Но это потребует любое изменение в таблице фиксить в таблице изменений, зато снимет нагрузку при сканировании изменений. 

Автор: MasterOfCode 22.9.2010, 09:22
Кстати, покопай в сторону DataSet, там вроде даже есть такое свойство, что-то вроде GetChanges.

Автор: mrbrooks 22.9.2010, 09:29
eon, это классическая проблема параллельного доступа

Цитата(eon @  22.9.2010,  09:11 Найти цитируемый пост)
Ситуация: при изменении (добавлении или удалении) записи в БД одним из клиентов, это изменение мгновенно должно отобразиться у всех клиентов в приложении в DataGrid.

думаю в этом тебе поможет MS Sync Framework.

Цитата(eon @  22.9.2010,  09:11 Найти цитируемый пост)
Есть способы: по таймеру обновлять (например каждую минуту), но эт неочень хороший способ.

Ужасный способ

Цитата(eon @  22.9.2010,  09:11 Найти цитируемый пост)
Есть способ с помощью триггеров. На сколько я знаю, производительность системы падает. Но мне в принципе подойдет этот способ, думаю небольшая нагрузка на сервер будет у меня.
Есть еще способы, более современные. 

Не до конца понимаю причем здесь обновления на клиенте. Больше похоже на таблицу аудита.
Цитата(MasterOfCode @  22.9.2010,  09:41 Найти цитируемый пост)
Интересный вопрос. Может в отдельном потоке делать запрос к БД на наличие изменений в таблице и делать refresh на клиенте?

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

хм. одно противоречит другому камрад. а отдельный поток как вызывать. раз в пол часа? 


Цитата(CYBERDREAM @  22.9.2010,  10:09 Найти цитируемый пост)
Ну а если создать табличку нечто вроде:
TableName | Action | Date

и как только какой то пользователь сделал изменнеие в какой то таблице, он делает запись в выше указанной, мол изменял данные в таблице "Таблица продуктов" | "Добавление" | "2010.10.03 14:45:09"

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

Добавлено через 4 минуты и 2 секунды
Но это потребует любое изменение в таблице фиксить в таблице изменений, зато снимет нагрузку при сканировании изменений. 

дык все одно придется опрашивать сначала таблицу аудита, а затем - по результатам - основную. сама по себе эта инфа не всплывет.
имхо. таблица аудита не кошерно. я настоятельно рекомендую ковырять MS Sync Framework, либо обрабатывать события параллельного доступа.

Добавлено через 1 минуту и 17 секунд
Цитата(MasterOfCode @  22.9.2010,  10:22 Найти цитируемый пост)
Кстати, покопай в сторону DataBindings, там вроде даже есть такое свойство, что-то вроде GetChanges. 

оно само не сработает камрад  smile 

Автор: MasterOfCode 22.9.2010, 09:34
Цитата(mrbrooks @  22.9.2010,  11:29 Найти цитируемый пост)
хм. одно противоречит другому камрад. а отдельный поток как вызывать. раз в пол часа? 

Не противоречит. К примеру у таблицы завести поле INSERT_DATE и UPDATE_DATE на триггер посадить их вставку.
Делать бычный селект на максимальное значение этого поля, если разнится запускать процедуру синхронизации с клиентом. Можно посадить это событие на OnShow формы. я думаю не будет сильно засорять канал как например:

второй способ это все данные тянуть каждую минуту.

Цитата

MS Sync Framework

Надо почитать.

Автор: jonie 22.9.2010, 09:36
мгновенно - надо смотреть имхо в сторону ServiceBroker-а. Т.е. схема такая: что-то инсертит данные в  таблицу, все делается через хранимку. Она делает вызов сервис брокера и кладет данные в его очередь. В свою очередь уже сервис брокер делает запрос к внешнему сервису, говоря об изменениях. Внешний сервис уведомляет тем или иным способом клиентов.

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

Цитата

дык все одно придется опрашивать сначала таблицу аудита, а затем - по результатам - основную. сама по себе эта инфа не всплывет.
имхо. таблица аудита не кошерно. я настоятельно рекомендую ковырять MS Sync Framework, либо обрабатывать события параллельного доступа.
В MSSQL2008 есть CDC (change data tracking) механизм. Я б использовал сканирование его. SyncFx будет лочить таблицы (исключая всякие там nolock хинты, но это может быть опасно в транзакциях), тогда как CDC нет, да и прост он очень даже....

Цитата


Не противоречит. К примеру у таблицы завести поле INSERT_DATE и UPDATE_DATE на триггер посадить их вставку.
Делать бычный селект на максимальное значение этого поля, если разнится запускать процедуру синхронизации с клиентом. Можно посадить это событие на OnShow формы. я думаю не будет сильно засорять канал как например:
не слушайте их, в MSSQL давно уже изобрен тип поля timestamp, для которого не нужны триггера.

Автор: mrbrooks 22.9.2010, 09:40
Цитата(MasterOfCode @  22.9.2010,  10:34 Найти цитируемый пост)
К примеру у таблицы завести поле INSERT_DATE и UPDATE_DATE на триггер посадить их вставку.

а как же удаление?


Цитата(MasterOfCode @  22.9.2010,  10:34 Найти цитируемый пост)
Делать бычный селект на максимальное значение этого поля, если разнится запускать процедуру синхронизации с клиентом. Можно посадить это событие на OnShow формы. я думаю не будет сильно засорять канал как например:
второй способ это все данные тянуть каждую минуту.

мне очень будет интересно посмотреть на сервер, где будет 100 таких клиентов. smile

Добавлено через 1 минуту и 12 секунд
Цитата(jonie @  22.9.2010,  10:36 Найти цитируемый пост)
не слушайте их, в MSSQL давно уже изобрен тип поля timestamp, для которого не нужны триггера.

во истину

Автор: jonie 22.9.2010, 09:45
Кстати о проблеме обработки событий (например от ServiceBrocker-а), кто-либо что-то знает об условиях лицензирования Microsoft StreamInsight [http://msdn.microsoft.com/en-us/library/ee362541.aspx]?

Автор: MasterOfCode 22.9.2010, 11:48
Цитата(mrbrooks @  22.9.2010,  11:40 Найти цитируемый пост)
мне очень будет интересно посмотреть на сервер, где будет 100 таких клиентов. smile

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

Цитата(mrbrooks @  22.9.2010,  11:40 Найти цитируемый пост)
а как же удаление?

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

Цитата(jonie @  22.9.2010,  11:36 Найти цитируемый пост)
не слушайте их, в MSSQL давно уже изобрен тип поля timestamp, для которого не нужны триггера.

Но суть идеи от этого не поменялась ;)

Добавлено через 9 минут и 26 секунд
Цитата(jonie @  22.9.2010,  11:36 Найти цитируемый пост)
мгновенно - надо смотреть имхо в сторону ServiceBroker-а. Т.е. схема такая: что-то инсертит данные в  таблицу, все делается через хранимку. Она делает вызов сервис брокера и кладет данные в его очередь. В свою очередь уже сервис брокер делает запрос к внешнему сервису, говоря об изменениях. Внешний сервис уведомляет тем или иным способом клиентов.

Использование ServiceBroker подразумевает собой держать постоянный коннект клиента с сервером?

Автор: mrbrooks 22.9.2010, 12:50
Цитата(MasterOfCode @  22.9.2010,  12:48 Найти цитируемый пост)
В любом случаи как бы этот вопрос не решить. В итоге все равно так или иначе все будет работать через сеть, и так же слать к серверу запросы. Засоряя сеть

я к тому - что велик с квадратными колесами делать не очень кошерно. все уже давно проработано до нас. есть стандартные решение предложенные выше. остальное - черная магия.

Цитата(MasterOfCode @  22.9.2010,  12:48 Найти цитируемый пост)
Цитата(mrbrooks @  22.9.2010,  11:40 Найти цитируемый пост)
а как же удаление?
Можно физически не удалять из базы, а выставлять признак. И раз в месяц делать делит в комбинации с рестрикт датабейс.

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

Автор: jonie 23.9.2010, 08:53
Цитата(MasterOfCode @  22.9.2010,  12:48 Найти цитируемый пост)

Использование ServiceBroker подразумевает собой держать постоянный коннект клиента с сервером?

протокол SOAP ложится поверх HTTP, на данный момент HTTP не подразумевает постоянного соединения впринципе.


Цитата(MasterOfCode @  22.9.2010,  12:48 Найти цитируемый пост)

В любом случаи как бы этот вопрос не решить. В итоге все равно так или иначе все будет работать через сеть, и так же слать к серверу запросы. Засоряя сеть
в случае сервис брокера не будет запросов к серверу, будут запросы от сервера.
Цитата(mrbrooks @  22.9.2010,  13:50 Найти цитируемый пост)

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

оставьте проблемы тормозов БД ДБАшникам. Они умеют всякие файловые группы делать, хитрые индексы и хинты к ним, и вооообще это не проблема.

Автор: JimCary 23.9.2010, 11:43
У меня стоит подобная задача: в БД содержатся документы при выборе которых для редактирования и при записи изменений по ним в БД клиенты должны получить об этом уведомление.

Пободавшись с проблемой я нашел ее решение с помощью WCF...

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

Не знаю конечно насколько такой вариант подойдет для вас, но мне подошел...

Автор: MasterOfCode 23.9.2010, 11:51
Цитата(JimCary @  23.9.2010,  13:43 Найти цитируемый пост)

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

А как же быть с обрывами связи? Если вдруг связь вырубится, документ так навсегда останется закрытым для редактирования?

Автор: JimCary 23.9.2010, 12:06
Ну во первых на сервере есть серверная-GUI часть, которая позволяет просмотреть кто и какой документ редактирует и позворляет удалять мертвые документы из списка... никто не запрещает встроить в серверную часть проверку наличия соединения с клиентами и по таймауту удалять ID из списка...
а во вторых, когда документ выбираеться для редактирования то вместе с ним в список редактируемых документов заносится сгенерированный GUID, который вместе с данными передается и клиенту, так что при востановлении связи с клиентом документ всегда будет сохранен тем кто его открыл...

Автор: jonie 23.9.2010, 12:36
JimCary, описывает типичную трехзвенную архитектуру, которую я уже предлагал :
Цитата


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

Автор: JimCary 23.9.2010, 12:58
Да, только ваш способ имеет один минус ServiceBroker  привязан к M$ SQL Server-у, а в моем случае база может быть любая (SQL Server  стоит денег и немалых)... да и WCF входит в состав Framework 3.5, так что используя бесплатную СУБД можно создавать приложения без больших затрат...

Автор: jonie 24.9.2010, 00:41
JimCary, вообще-то СерсисБрокер никак не писывается в типичную трехзвенку, да и не имел я его в виду вообще говоря про то предложение.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)