Пример #1
0
        private void CalculateFromDate <TMessage, TItem>(ref DateTime?fromDate)
            where TMessage : IDataChangeMessageResponce <TItem>
            where TItem : IChangedItem
        {
            var lastSyncTMessage = SyncAdapterTools.GetLastSendMessage <TMessage>();

            if (lastSyncTMessage?.ChangesTo == null)
            {
                if (fromDate == null)
                {
                    LogService.LogWarn(
                        $"{LogWarnMessageHeader} Не задана дата с которой брать изменения и не удалось определить дату из последнего sync-сообщение типа {typeof(TMessage).Name}. Факты-изменения будут обработаны с самого начала!");
                }
            }
            else
            {
                if (fromDate != null)
                {
                    if (lastSyncTMessage.ChangesTo > fromDate)
                    {
                        LogService.LogWarn(
                            $"{LogWarnMessageHeader} Дата с которой планировалось отправить изменения меньше, чем дата отправки последнего sync-сообщение типа {typeof(TMessage).Name}. Дата начала отправки изменений была изменена с {fromDate.Value:G} на {lastSyncTMessage.ChangesTo.Value:G}");
                        fromDate = lastSyncTMessage.ChangesTo;
                    }
                }
                else
                {
                    fromDate = lastSyncTMessage.ChangesTo;
                }
            }
        }
Пример #2
0
        private Function GetSyncEntityLimitForDataChangeMessageResponce <TItem>(DateTime?fromDate, DateTime?toDate)
            where TItem : IChangedItem
        {
            var timeFunc = FunctionBuilder.BuildTrue();

            if (fromDate != null || toDate != null)
            {
                if (fromDate != null && toDate != null)
                {
                    timeFunc = FunctionBuilder.BuildBetween <SyncDOEntity>(x => x.Date, fromDate, toDate);
                }
                else if (fromDate != null)
                {
                    timeFunc = FunctionBuilder.BuildGreater <SyncDOEntity>(x => x.Date, fromDate);
                }
                else
                {
                    timeFunc = FunctionBuilder.BuildLessOrEqual <SyncDOEntity>(x => x.Date, toDate);
                }
            }

            var typesFunc = FunctionBuilder.BuildTrue();
            var supTypes  = SyncAdapterTools.GetSupportTypeForChangedItem <TItem>();

            if (supTypes.Any())
            {
                typesFunc = FunctionBuilder.BuildIn <SyncDOEntity>(x => x.Setting.Source.Name,
                                                                   supTypes.Select(x => x.FullName));
            }

            return(FunctionBuilder.BuildAnd(FunctionBuilder.BuildIsNotNull <SyncDOEntity>(x => x.Date), timeFunc,
                                            typesFunc));
        }
Пример #3
0
        /// <inheritdoc />
        public virtual void PackChanges <TMessage, TItem>(DateTime?fromDate = null, DateTime?toDate = null)
            where TMessage : IDataChangeMessageResponce <TItem>
            where TItem : IChangedItem
        {
            //Перевычисляем дату с которой будет собирать изменения, что бы не отправить изменения повторно.
            CalculateFromDate <TMessage, TItem>(ref fromDate);
            LogService.LogInfo(
                $"ChangePackageCollector: Начата обработка фактов-изменений для сообщения типа {typeof(TMessage).Name}{Helper.GetDatePartAsString(fromDate, toDate)}.");

            try
            {
                //Узнаём сколько фактов-изменений было за период с последний отправки изменений.
                var syncEntityView = SyncDOEntity.Views.E;
                syncEntityView.AddProperties(Information.ExtractPropertyPath <SyncDOEntity>(x => x.Setting.Source.Name));
                var lcs = LoadingCustomizationStruct.GetSimpleStruct(typeof(SyncDOEntity), syncEntityView);
                lcs.ColumnsSort   = new[] { new ColumnsSortDef(nameof(SyncDOEntity.Date), SortOrder.Asc) };
                lcs.LimitFunction = GetSyncEntityLimitForDataChangeMessageResponce <TItem>(fromDate, toDate);
                var loadingCount = GetSyncDOEntityCount(lcs);

                if (loadingCount > 0)
                {
                    //Определяем размер пакета которым будут отправлены изменения.
                    var packageSize = SyncAdapterTools.GetPackageSizeForMessage <TMessage>();

                    //Размер порции одной вычитки определяет размерность пакета сообщения.
                    lcs.LoadingBufferSize = packageSize;
                    //Состояние сервиса данных, для порционной вычитки.
                    object state          = null;
                    var    syncDoEntities = GetSyncDOEntity(lcs, ref state);

                    LogService.LogInfo(
                        $"ChangePackageCollector: Всего фактов-изменений для сообщения типа {typeof(TMessage).Name} - {loadingCount}, размер одного пакета установлен в {packageSize}.");
                    var currentNumPackage = 0;
                    var totalNumPackage   = loadingCount / packageSize;


                    //Пока дата сервис возвращает факты-изменения.
                    while (syncDoEntities.Count > 0)
                    {
                        currentNumPackage++;
                        LogService.LogInfo(
                            $"ChangePackageCollector: Обрабатывается {currentNumPackage} порция фактов-изменений из {totalNumPackage}.");

                        var changedItems = new List <TItem>();
                        //Обрабатываем вычитанную порцию фактов-изменений.
                        foreach (var syncEntity in syncDoEntities)
                        {
                            //Получаем настройки для обработки факта-изменения.
                            GetSyncSettings(syncEntity, out var type, out var mapper, out var appObjPrimaryKey);

                            if (syncEntity.Date != null &&
                                syncEntity.AuditChangePK != null)
                            {
                                var appObject = GetDataObjectBySyncEntity(appObjPrimaryKey, type, syncEntity.ObjectStatus, syncEntity.Date.Value);

                                List <string> changedFields = null;
                                if (SyncAdapterTools.GetSendChangedFieldAttributeForMessage <TMessage>())
                                {
                                    changedFields = GetChangedFieldBySyncEntity(syncEntity.ObjectStatus, syncEntity.AuditChangePK.Value);
                                }

                                //маппим объект в xml объект
                                var xmlObjects = GetXMLObjectByMapper(mapper, appObject);

                                //Cкладываем xml-объект в список, который будет передан создателю сообщения об изменении.
                                changedItems.AddRange(xmlObjects.Select(x => CreateChangedItem <TItem>(syncEntity, x, changedFields)));
                            }
                        }

                        //После обработки всех фактов-изменений, создаём сообщение-изменение нужного типа.
                        //Реальный размер объектов-изменения в сообщении может быть больше указанного размера пакета, это происходит из-за преобразований одного объкта в несколько при маппинге.
                        var message = new DataChangesCreator <TMessage, TItem>(changedItems).CreateMessage();
                        message.Save();

                        //Вычитываем очередную порцию фактов-изменений.
                        syncDoEntities = GetSyncDOEntity(null, ref state);
                    }

                    LogService.LogInfo(
                        $"ChangePackageCollector: Успешное завершение обработки фактов-изменений для сообщения типа {typeof(TMessage).Name}{Helper.GetDatePartAsString(fromDate, toDate)}.");
                }
                else
                {
                    LogService.LogInfo(
                        $"ChangePackageCollector: Нет новых фактов-изменений для сообщения типа {typeof(TMessage).Name} с изменениями {Helper.GetDatePartAsString(fromDate, toDate)}. Синхронизационные сообщения сформированы не будут!");
                }
            }
            catch (Exception ex)
            {
                LogService.LogError($"{LogErrorMessageHeader} Операция будет прервана!", ex);
                throw;
            }
        }