/// <summary> /// Запаковывает изменения. /// Метод можно разбить на несколько кусков, чтобы можно было модифицировать при прикладном использовании. /// </summary> /// <param name=""></param> public void PackChanges(Packaging) { // Догрузить Packaging. DataService.LoadObject(Packaging); // Период изменений. // Если только dateFrom == null, то брать все изменения до dateTo. // Если только dateTo, то брать изменения начиная с dateFrom. // Если обе даты == null, то брать все изменения. DateTime dateFrom = PackageCollecting.DateFrom; DateTime dateTo = PackageCollecting.DateTo; // Читаем факты изменения из БД. // Выбираем только факты нужных классов. // Сортируем по дате. // Порционная вычитка опущена для простоты. seClassLimit = In <SyncEntity>(se => se.ClassName, mappingClassNames); var syncEntities = DataService.LoadObjects(seClassLimit); foreach (var se in syncEntities) { // Проверим, было ли запаковано изменение в данной синхронизации. // Текущая идея - проверять существование такого ObjectChangePackage: packagedLimit = And( Equals <ObjectChangePackage>(ocp => ocp.Package.Packaging.Synchronization, SyncID), Equals <ObjectChangePackage>(ocp => ocp.syncEntity, se) ); var objectChangePackage = DataService.LoadObjects(packagedLimit).FirstOrDefault(); // Если было, то попробовать взять готовый пакет. if (objectChangePackage != null) { if (objectChangePackage.data != null) { MessageBuilder.AppendMessage(packaged); } // Если готового пакета нет, то запаковываем. } else { // Выполняем чтение и маппинг. // Если обозреваемый объект превращается в несколько целевых объектов, то маппетов будет несколько. // Базовый механизм маппинга будет таким же, как в прошлом синхронизаторе. var currentMappers = mappers.Where(map => map.GetObservingType() == se.type); foreach (var currentMapper in currentMappers) { // Если еще не запаковывали, то читаем сами изменения из БД приложения. // Тут должно быть по-разному: вариант для старого аудита, и вариант для нового аудита. // Чтение уже реализовано в предыдущих вариантах синхронизаторов. // Например, прочитаем со старым аудитом. // Должны получить сам объект, тип объекта и список измененных атрибутов. var change = PackageHelper.GetChangeFromAppDB(se, tAuditType.Old, map.GetObservingView()); // Получаем целевые объекты. var destinationObject = currentMapper.Map(change); // Собираем сообщение. // Скорее всего, messageBuilder будет сам решать, как собирать пакеты, поэтому просто отправлем ему всю информацию об изменениях. messageBuilder.CreateMessage(destinationObject, change, objectChangePackage); } } // Как только пакет в messageBuilder готов, достаем его и все его сообщения. var package = messageBuilder.PopPackage(); if (package != null) { // Пакет сообщения складываем в бд. DataService.UpdateObject(package); package = null; } } // Создать пакет из оставшихся сообщений. var forcedPackage = messageBuilder.PopPackageForced(); DataService.UpdateObject(forcedPackage); // Теперь в бд лежат пакеты и составляющие сообщения. // Если это будет занимать слишком много памяти, // то можно очищать ObjectChangePackage.data (можно и не хранить, но тогда иногда придется упаковывать по нескольку раз) // и Package.data (после успешной синхронизации). // Как часто поток будет искать в БД объект Package. Thread.Sleep(10000); }