Добавление централизованной базы данных для существующего приложения C# Win
У нас есть приложение для Windows с локальной базой данных. Мало кто из наших клиентов запрашивает централизованный отчет со всего своего местоположения. Наше предлагаемое решение - иметь центральную базу данных в головном офисе клиента по статическому IP и синхронизировать все данные с помощью службы WCF.
Поскольку центральный сервер может быть доступен не всегда, мне нужно простое решение, чтобы узнать из каждой автономной базы данных все записи, которые не синхронизированы с центральной базой данных. Так что служба синхронизации во внутреннем сервере копирует все оставшиеся данные в центральную БД.
одна опция - иметь логический столбец во всех таблицах как IsSynched, чтобы указать, синхронизирован ли он. Но это требует большого изменения кода во всех ссылочных процедурах и коде.
Любое альтернативное решение?
3 ответа
Я бы предположил, что логический IsSynced очень и очень слаб с точки зрения синхронизации. Если офис дольше не работает, вам, безусловно, будет трудно все успеть.
Если вы добавите столбец VersionNumber, вы будете знать, что каждая строка с VersionNumber ниже фактического VersionNumber нуждается в обновлении.
Более сложным подходом может быть добавление столбца LastUpdated TimeStamp в каждую таблицу, что может сэкономить некоторый трафик, поскольку VersionNumber может увеличиться и может содержать обновление строки, но не может! Принимая во внимание, что LastUpdated от того, что я вижу, является специфичным для строки и создает возможность извлекать (= обновлять) только те данные (= строки), которые являются более новыми, чем самая новая запись в вашей (= центральной) всей базе данных. Который на самом деле может работать как денди.
Несколько вещей для рассмотрения:
- Почему центральная БД не всегда будет доступна?
- Будут ли отчеты выполняться в центральной или локальной БД?
- Требуется ли двухсторонняя синхронизация (локальная <-> центральная)?
- Насколько надежным будет соединение во время синхронизации?
Решение, которое я недавно унаследовал, обрабатывает это следующим образом:
- Служба Windows работает в фоновом режиме - она отвечает за синхронизацию. Местного приложения нет.
- Для центральной -> локальной синхронизации каждая запись имеет столбец last_updated (DateTime). Это обновляется до CURRENT_TIMESTAMP каждый раз, когда происходит обновление записи. Для каждой таблицы в локальной БД служба Windows проверяет наличие самой новой отметки времени записи. Запрос запускается к соответствующей таблице в центральной БД, чтобы получить какие-либо новые / обновленные записи, то есть что-то вроде
SELECT * FROM central.table WHERE last_update > @lastLocalUpdate;
, Все результаты вставляются / обновляются в локальной БД. - Для локальной -> центральной синхронизации каждая запись в локальной БД имеет только столбец is_sent (логический). Это значение false каждый раз, когда происходит локальное обновление записи. Для каждой таблицы в локальной БД служба Windows проверяет записи, которые не были отправлены в центральную БД, т.е.
SELECT * FROM local.table WHERE is_sent = 0;
, Все результаты вставляются / обновляются в центральной БД, а затем is_sent устанавливается в 1.
Это немного болтливо, но в конечном итоге это работает. В моем случае локальное устройство часто теряет связь, так что этот тип детализации работает.
В моем списке пожеланий стоит полностью пересмотреть этот механизм и реализовать очередь сообщений.
РЕДАКТИРОВАТЬ: если вы настаиваете, что не хотите вносить какие-либо изменения в существующую кодовую базу, вы можете реализовать обновления last_updated / is_sent на уровне SQL и иметь синхронизацию. Сервис как совершенно отдельный проект. "Невидимые обновления" не помогут найти самое чистое решение, но, эй, выбирайте свои сражения.
Похоже, вам нужно реализовать репликацию с несколькими хозяевами или с несколькими источниками. Репликация с несколькими мастерами - очень сложное решение для реализации самостоятельно.
Я сделал это следующим образом: вам понадобятся триггеры для каждой таблицы (вставка, удаление, обновление), чтобы отслеживать все изменения, внесенные в каждую строку, в таблицу "отслеживания изменений" (вы должны убедиться, что триггеры остаются с любой БД / таблица обновлений). Таблица изменений будет нуждаться в глобально уникальном ключе (ключах) (обычно это комбинация уникального "кода сайта" и уникального идентификатора каждой строки), типа изменения, даты и времени изменения UTC, имени таблицы, идентификатора строки и статус репликации (т.е. дата отправки) каждой строки CRUD. Вы используете таблицу отслеживания изменений со службами WCF для синхронизации клиента с таблицами сервера. Вы также должны убедиться, что они содержат одни и те же данные, прежде чем запускать систему репликации (возможно, загрузив сайты db в центральную базу данных в начале).
Если вы можете переключиться на другую БД, последняя версия MariaDB включает эту функциональность "из коробки" ( https://mariadb.com/kb/en/multi-source-replication/) бесплатно. Такая функциональность на уровне базы данных значительно облегчит эту задачу.
В качестве альтернативы, в зависимости от вашего бюджета и СУБД, может быть какой-нибудь готовый продукт для репликации, чтобы помочь вам?