из одной базы данных в другую базу данных

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

И вот замеченно, что если приложение которое работает со старой базой отключенно или bug в сети, вообщем если два api не договорили на заднем фоне, то данные просто сохраняются в новой базе и старая потом об этом ничего не узнает, а мобильное приложение отправляет мессаж что мол данные синхронизированны успешно, только вот потом не состыковка с данными случается.

Таким образом мне думается, что необходимо следующее, создать таблицу в новой базе данных с объектами, которые не удалось синхронизировать потом метод в сервисе дополнительный чтобы получать ответ от api 1 и уже при повторном подключении запускать заново объекты для обновления в данной таблице до синхронизации с мобильным приложением.

Вопрос : какие данные должна содержать данная таблица ? И есть ли другие решения

        [Key]
        public long Id { get; set; }

        public long? ObjectId { get; set; }

        [ForeignKey(nameof(ObjectId))]
        public Object Object { get; set; }

        public DateTime Date { get; set; } 

        // for example if error < 2, check properties, maybe some information is not correct in that object
        public int ErrorSynchronization { get; set; } 

в старой базе данных бывают "сюрпризы" например однажды приложение выдавало ошибку при сохранении одного эллемента и я заметила, что в базе данных есть ограничения для одного из свойст (varchar 5) а клиент сохраняет например 8 символов, это не было нигде зафиксированно, как уже повторюсь база старая и не мало кто на ней работал...поэтому предусматриваю int ErrorSynchronization, например если первый, второй раз все еще остается не синхронизированным и число int думаю надо +1 возможно надо проанализировать все свойства данного объекта

// api 2 создает таблицы через Entity Framework, работаю я на C#, база на sql => поэтому и метки соответствующие

p.s. вопрос, а тот кто ставит минус это обосновывается, или может быть просто хоп и минус поставил, сама не ставила еще минусы поэтому интересуюсь


Ответы (2 шт):

Автор решения: Sergei Kirjanov

Можно создать таблицу в новой базе данных с задачами на синхронизацию.

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

Изменения и номер последней примененной задачи запишутся в одной транзакции.

→ Ссылка
Автор решения: Dev18

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

в момент когда мы сохраняем объекты как обычно, если вдруг api1 не ответило, мы сохраняем объекты в данной временной таблице, затем

ДЛЯ ПОВТОРНОЙ ПОПЫТКИ ЗАПИСИ в АПИ1

создаем дополнительный HookController

[HttpGet]
public async Task<ActionResult> RunSynchronizations()
{
    await synchronizationService.SendUnsynchronizedObjectsAsync().ConfigureAwait(false);
    return Ok();
}

а в нашем api1 в Startup (чтобы как только приложение стало активно) классе зовем данный контроллер (общаются два апи через Refit...) и таким образом как только api1 запускается, api2 просматривает нашу временную таблицу с объектами, которые не были синхронизированны. и повторяет процедуру CRUD (записывает, удаляет, изменяет...)

public Task SendUnsynchronizedObjectsAsync()
{
    return Task.Run(() =>
    {
        var dbSet = dbContext.Set<ObjectsoSendToApi1>(); // наша временная таблица

        var objetctsToSynchronize = dbSet.Include(s => s.Object).ToList(); 
        // include чтобы добавить основной объект

        Task[] toAwait = new Task[objetctsToSynchronize.Count];

        // берем все объекты из временной таблицы
        for (var i = 0; i < objetctsToSynchronize.Count; i++)
        {
            toAwait[i] = SendToApi1ForSaveAsync(objetctsToSynchronize[i].Object);
            /* метод SendToApi1ForSaveAsync повторно сохраняет...
            и catch если повторно api1 не отвечает и так по кругу... */
        }

        // и удаляем объекты из временной таблицы
        dbSet.RemoveRange(objetctsToSynchronize); 
        
        Task.WaitAll(toAwait); 

        dbContext.SaveChanges(); // сохраняем изменения
    });
}
→ Ссылка