public void GetGuidByObjectСравнениеGuid()
        {
            var obj = PKHelper.CreateDataObject <DataObjectForTest>(g1);

            Assert.True(
                PKHelper.EQPK(g1, PKHelper.GetGuidByObject(obj)),
                "Возвращенный Guid не равен исходному.");
        }
        public static void GetObjForDate(DateTime date, ref DataObject obj, Guid?changeAuditPK = null,
                                         bool onlySelfObj = true)
        {
            if (obj != null)
            {
                try
                {
                    //Загружаем текущее состояние объекта по выбранному представлению
                    obj.DisableInitDataCopy();
                    //это объект никогда не будет сохраняться в бд, копия данных -, производительность +
                    DataService.LoadObject("AuditView", obj, true, false);
                }
                catch (Exception ex)
                {
                    //throw new LoadChangedObjectException(appObjType.Name, appObjPK, ex.Message);
                    LogService.LogError("Ошибка при вычитке объекта из бд");
                    //TODO поймать исключение о существовании объекта
                    //объект в текущий момент может быть удалён, тогда его нельзя будет загрузить из бд
                    // нужно ли вообще по нему что-то высылать кроме ключа елси его он всё равно будет удалён следующими сообщениями?
                    //Объект восстановиться, если ведется аудит удаления для него - запись удаленя - это занулление всех текущих значений
                }

                var changedAuditEntity = new List <AuditEntity>();
                try
                {
                    var lcs = LoadingCustomizationStruct.GetSimpleStruct(typeof(AuditEntity),
                                                                         AuditEntity.Views.AuditEntityE);
                    lcs.LimitFunction = FunctionBuilder.BuildAnd(
                        FunctionBuilder.BuildEquals(nameof(AuditEntity.ObjectPrimaryKey), obj.__PrimaryKey),
                        FunctionBuilder.BuildGreaterOrEqual <AuditEntity>(x => x.OperationTime, date));
                    lcs.ColumnsSort    = new[] { new ColumnsSortDef(nameof(AuditEntity.OperationTime), SortOrder.Desc) };
                    changedAuditEntity = DataService.LoadObjects(lcs).Cast <AuditEntity>().ToList();
                }
                catch (Exception ex)
                {
                    LogService.LogError(@"Ошибка при загрузке операций изменения из аудита");
                }

                var lastChange = changedAuditEntity.LastOrDefault();
                if (changeAuditPK.HasValue && PKHelper.GetGuidByObject(lastChange) != changeAuditPK)
                {
                    LogService.LogError(
                        @"Ошибка сбой при загрузке изменеий! Обнаружено не соответствиие загруженных изменений и ссылки на изменения аудита в synclogitem");
                }

                var objType        = obj.GetType();
                var auditFieldsLcs = LoadingCustomizationStruct.GetSimpleStruct(typeof(AuditField), ViewForField);
                foreach (var changeEntity in changedAuditEntity)
                {
                    if (changeEntity.OperationType != operationCreateType)
                    {
                        var changedFields = new List <AuditField>();
                        try
                        {
                            auditFieldsLcs.LimitFunction =
                                FunctionBuilder.BuildEquals <AuditField>(x => x.AuditEntity, changeEntity);
                            changedFields = DataService.LoadObjects(auditFieldsLcs).Cast <AuditField>().ToList();
                        }
                        catch (Exception ex)
                        {
                            LogService.LogError(
                                $@"Произошла ошибка при попытке получить набор изменения изменения полей за период.{
                                        Environment.NewLine
                                    }{ex.Message}");
                        }

                        //Берём только изменения, вспомогательные объекты LinkedPrimaryKey остаются в основном списке
                        var onlySelfChangedFields = changedFields.Where(y => y.MainChange == null);

                        foreach (var changedField in onlySelfChangedFields)
                        {
                            var mainChange =
                                changedFields.FirstOrDefault(x => PKHelper.EQPK(x.MainChange, changedField));
                            if (mainChange == null)
                            {
                                //Если основного изменения нет, то это обычное поле
                                var propertyInfo = objType.GetProperty(changedField.Field);
                                if (propertyInfo != null)
                                {
                                    var    typeprop = propertyInfo.PropertyType;
                                    object value    = null;
                                    try
                                    {
                                        if (changedField.OldValue != null)
                                        {
                                            value = Convert.ChangeType(changedField.OldValue, typeprop);
                                        }

                                        propertyInfo.SetValue(obj, value);
                                    }
                                    catch (Exception ex)
                                    {
                                        LogService.LogError(value != null
                                            ? $"Ошибка установки поля {changedField.Field}"
                                            : $"Ошибка преобразования типа полей");
                                    }
                                }
                                else
                                {
                                    LogService.LogError(
                                        $@"Ошбика не найдено поле {changedField.Field} в объекте {objType.Name}.");
                                }
                            }
                            else
                            {
                                // В аудите детейл отличается от мастера тем, что у него приписывается в скобках позиция
                                if (Regex.IsMatch(changedField.Field, "[ ][(][0-9]+[)]$"))
                                {
                                    var separateIndex       = changedField.Field.IndexOf(" ", StringComparison.Ordinal);
                                    var detailNameFromField = changedField.Field.Substring(0, separateIndex);
                                    var propertyInfo        = objType.GetProperty(detailNameFromField);
                                    if (propertyInfo != null)
                                    {
                                        var detailValue = propertyInfo.GetValue(obj) as DetailArray;
                                        if (detailValue != null)
                                        {
                                            //TODO исследовать возможность пустой ссылки на детейл
                                            if (changedField.OldValue == "-NULL-")
                                            {
                                                var key = new KeyGuid(mainChange.NewValue);
                                                detailValue.RemoveByKey(key);
                                            }
                                            else
                                            {
                                                var detailItemType = detailValue.ItemType;
                                                var oldDetailObj   =
                                                    GetInstanseOfObjWithPK(detailItemType, mainChange.OldValue);
                                                detailValue.AddObject(oldDetailObj);
                                            }
                                        }

                                        /*else
                                         * {
                                         *  LogService.LogError(
                                         *      $@"Ошибка не найден детейл {detailNameFromField} в объекте {objType.Name}.");
                                         * }*/
                                    }
                                    else
                                    {
                                        LogService.LogError(
                                            $@"Ошибка не найден детейл {
                                                    detailNameFromField
                                                } в объекте {objType.Name}.");
                                    }
                                }
                                else
                                {
                                    var propertyInfo = objType.GetProperty(changedField.Field);
                                    if (propertyInfo != null)
                                    {
                                        // Это изменение мастера.
                                        if (changedField.OldValue == "-NULL-")
                                        {
                                            propertyInfo.SetValue(obj, null);
                                        }
                                        else
                                        {
                                            var typeprop     = propertyInfo.PropertyType;
                                            var oldMasterObj = GetInstanseOfObjWithPK(typeprop, mainChange.OldValue);
                                            propertyInfo.SetValue(obj, oldMasterObj);
                                        }
                                    }
                                    else
                                    {
                                        LogService.LogError(
                                            $@"Ошбика не найден мастер {changedField.Field} в объекте {objType.Name}.");
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // Если откатываем создание объекта, то возвращаем нулл.
                        obj = null;
                    }
                }

                // На этом этапе основной объект и все его собственные поля и зависимые сущности возвращены на дату
                // Получаем мастера и откатываем их поля, рекурсивно вызывая этот метод
                // Получаем детейлы объекта и откатываем их поля, рекурсивно вызывая этот метод
                if (!onlySelfObj)
                {
                    var objProperties = objType.GetProperties();
                    foreach (var property in objProperties)
                    {
                        var typeprop = property.PropertyType;
                        if (typeprop.IsSubclassOf(typeof(DataObject)))
                        {
                            //Перебираем все мастера
                            var masterValue = property.GetValue(obj) as DataObject;
                            GetObjForDate(date, ref masterValue, null, onlySelfObj);
                        }
                        else if (typeprop.IsSubclassOf(typeof(DetailArray)))
                        {
                            //Перебираем все детейлы
                            var detailValue   = property.GetValue(obj) as DetailArray;
                            var detailObjects = detailValue.GetAllObjects();
                            foreach (var dataObject in detailObjects)
                            {
                                var currentObj = dataObject;
                                GetObjForDate(date, ref currentObj, null, onlySelfObj);
                            }
                        }
                    }
                }
            }
        }
        private static AuditChange GetChangesByPeriodByPK(DateTime from, DateTime until, string objPk, bool firstLoop,
                                                          bool recursive)
        {
            var операцииЗаПериод = new List <AuditEntity>();

            try
            {
                var lcs = LoadingCustomizationStruct.GetSimpleStruct(typeof(AuditEntity),
                                                                     AuditEntity.Views.AuditEntityE);
                lcs.LimitFunction = FunctionBuilder.BuildAnd(
                    FunctionBuilder.BuildEquals(nameof(AuditEntity.ObjectPrimaryKey), objPk),
                    FunctionBuilder.BuildBetween <AuditEntity>(x => x.OperationTime, from, until));
                операцииЗаПериод = DataService.LoadObjects(lcs).Cast <AuditEntity>().OrderBy(x => x.OperationTime)
                                   .ToList();
            }
            catch (Exception ex)
            {
                LogService.LogError(
                    $@"Произошла ошибка при попытке получить изменения за период {from.ToShortDateString()} - {
                            until.ToShortDateString()
                        } для объекта с ключом {objPk}.{Environment.NewLine}{ex.Message}");
            }

            var итоговыйСтатусОбъекта = GetAuditOperationType(операцииЗаПериод);
            var изменениеОбъекта      = new AuditChange
            {
                Type          = GetObjTypeByPK(objPk),
                ObjPrimaryKey = objPk,
                Operation     = итоговыйСтатусОбъекта
            };

            if (итоговыйСтатусОбъекта != tAuditOperation.CreateAndDelete &&
                итоговыйСтатусОбъекта != tAuditOperation.NoChange &&
                (firstLoop || recursive))
            {
                var fieldsLcs = LoadingCustomizationStruct.GetSimpleStruct(typeof(AuditField), ViewForField);
                foreach (var операцияИзменения in операцииЗаПериод)
                {
                    var измененияПолей = new List <AuditField>();
                    try
                    {
                        fieldsLcs.LimitFunction = FunctionBuilder.BuildEquals <AuditField>(x => x.AuditEntity,
                                                                                           операцияИзменения);
                        измененияПолей = DataService.LoadObjects(fieldsLcs).Cast <AuditField>().ToList();
                    }
                    catch (Exception ex)
                    {
                        LogService.LogError(
                            $@"Произошла ошибка при попытке получить набор изменения изменения полей за период {
                                    from.ToShortDateString()
                                } - {until.ToShortDateString()} для объекта с ключом {objPk} для изменения с ключом {
                                    операцияИзменения.__PrimaryKey
                                }.{Environment.NewLine}{ex.Message}");
                    }

                    var толькоСобственныеИзменения = измененияПолей.Where(
                        y => y.MainChange != null ||
                        !измененияПолей.Exists(x => PKHelper.EQPK(x.MainChange, y)));

                    foreach (var измененныйАтрибут in толькоСобственныеИзменения)
                    {
                        if (измененныйАтрибут.MainChange == null)
                        {
                            // Это изменение собственного поля.
                            изменениеОбъекта.FieldsChanges[измененныйАтрибут.Field] = измененныйАтрибут.NewValue;
                        }
                        else
                        {
                            var главноеИзменение =
                                измененияПолей.First(x => PKHelper.EQPK(x, измененныйАтрибут.MainChange));
                            if (Regex.IsMatch(главноеИзменение.Field, "[ ][(][0-9]+[)]$"))
                            {
                                // Это изменение детейла.
                                var номерДетейла = Regex.Match(главноеИзменение.Field, "[ ][(][0-9]+[)]$").Value;
                                // Если ссылка на детейл стала нулл, то соберём изменение удаления этого объекта.
                                var ключДетейла = измененныйАтрибут.NewValue == "-NULL-"
                                    ? измененныйАтрибут.OldValue
                                    : измененныйАтрибут.NewValue;

                                // Заменяем номер детейла на ключ объекта. Так как номер переприсваевается следующими по порядку детейлу,
                                // в качестве ключа изменения детейла используем тип детейла и его первичного ключа заключенный в между@@
                                изменениеОбъекта.DetailsChanges[
                                    главноеИзменение.Field.Replace(номерДетейла, $"@{ключДетейла}@")] =
                                    GetChangesByPeriodByPK(from, until, ключДетейла, false, recursive);
                            }
                            else
                            {
                                // Это изменение мастера.
                                // Если ссылка на мастра стала нулл, то и изменения не будем собирать, возвращаем нулл.
                                изменениеОбъекта.MastersChanges[главноеИзменение.Field] =
                                    измененныйАтрибут.NewValue == "-NULL-"
                                        ? null
                                        : GetChangesByPeriodByPK(from, until, измененныйАтрибут.NewValue, false,
                                                                 recursive);
                            }
                        }
                    }
                }
            }

            return(изменениеОбъекта);
        }
 public void GetKeyByObjectСравнениеGuid()
 {
     Assert.True(
         PKHelper.EQPK(g1, PKHelper.GetKeyByObject(g1)),
         "Возвращенный KeyGuid не равен исходному Guid.");
 }
 public void EQPKСравнениеОбъектовСРазнымиGuid()
 {
     Assert.True(
         !PKHelper.EQPK(doft1, doft2),
         "Объекты с разными Guid сравнены неверно.");
 }
        public void EQPKСравнениеОбъектовСОдинаковымиGuid()
        {
            var obj2 = PKHelper.CreateDataObject <DataObjectForTest>(doft0);

            Assert.True(PKHelper.EQPK(doft0, obj2), "Объекты с одинаковыми Guid сравнены неверно.");
        }
 public void EQPKСравнениеОбъектовСКлючомИБезКлючом()
 {
     Assert.True(!PKHelper.EQPK(new object(), doft0), "Объект с ключом и объект без ключа сравнены неверно.");
 }
 public void CreateDataObjectСравнениеКлючей()
 {
     Assert.True(PKHelper.EQPK(kg1, doft1), "Метод вернул объект с неверным ключом.");
 }
 public void EQPKСравнениеПустогоОбъектаИСКлючом()
 {
     Assert.True(!PKHelper.EQPK(null, doft0), "Пустой объект и объект с ключом сравнены неверно.");
 }
 public void EQPKСравнениеОбъектовБезКлючей()
 {
     Assert.True(!PKHelper.EQPK(new object(), new object()), "Объекты без ключей сравнены неверно.");
 }
 public void EQPKСравнениеПустогоОбъектаИБезКлюча()
 {
     Assert.True(!PKHelper.EQPK(null, new object()), "Пустой объект и объект без ключа сравнены неверно.");
 }
 public void EQPKСравнениеПустыхОбъектов()
 {
     Assert.True(!PKHelper.EQPK(null, null), "Пустые объекты сравнены неверно.");
 }
 public void GetGuidByObjectСравнениеString()
 {
     Assert.True(
         PKHelper.EQPK(str1, PKHelper.GetKeyByObject(str1)),
         "Возвращенный Guid не равен исходному string.");
 }
Beispiel #14
0
        /// <summary>
        /// Получить объект на заданную дату.
        /// </summary>
        /// <param name="date">Дата на которую следует откатить состояние объекта</param>
        /// <param name="obj">Объект, который откатываем на заданную дату.</param>
        /// <param name="onlySelfObj">Откатывать только сам объект, т.е. в обратное состояния вернутся все собственные поля объекта и все собственные ссылочные объекты(мастра и детейлы) только ключи</param>
        /// <param name="forceNullAgregator">Объект вернётся в состояние сразу после заданной даты.
        ///  Если откатываем создание объекта, то возвращаем путой объект с первичным ключом.
        ///  Если объект был удалён и ведётся аудит удаления, то он будет восстановлен со всеми своими собственными полями, иначе если аудит удаления отключен, у удаленного объекта будет проинициализирован только первичный ключ.
        /// </param>
        public static void GetObjForDate(DateTime date, ref DataObject obj, bool onlySelfObj = true,
                                         bool forceNullAgregator = false)
        {
            if (obj != null)
            {
                var objType = obj.GetType();
                try
                {
                    obj.DisableInitDataCopy();
                    // Не кидается исключение о не существовании объекта, если объект был удалён и ведётся аудит удаления, то он будет восстановлен со всеми своими собственными полями, иначе если аудит удаления отключен, у удаленного объекта будет проинициализирован только первичный ключ.
                    DataServiceFactory.AppDataService.LoadObject(new View(objType, View.ReadType.WithRelated), obj,
                                                                 true, false);
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке вычитать изменнённый объект из БД. {ex.Message}");
                }

                List <AuditEntity> changedAuditEntity;
                try
                {
                    var lcs = LoadingCustomizationStruct.GetSimpleStruct(typeof(AuditEntity),
                                                                         AuditEntity.Views.AuditEntityE);
                    lcs.LimitFunction = FunctionBuilder.BuildAnd(
                        #pragma warning disable CS0618 // Используем не дженерик вариант, иначе не работает вычитка
                        FunctionBuilder.BuildEquals(nameof(AuditEntity.ObjectPrimaryKey), obj.__PrimaryKey),
                        #pragma warning restore CS0618 // Тип или член устарел
                        FunctionBuilder.BuildGreater <AuditEntity>(x => x.OperationTime, date));
                    // Загружаем изменения строго больше даты на которую хотим откатить => получаем объект в состоянии сразу после этой даты.
                    lcs.ColumnsSort    = new[] { new ColumnsSortDef(nameof(AuditEntity.OperationTime), SortOrder.Desc) };
                    changedAuditEntity =
                        DataServiceFactory.AppDataService.LoadObjects(lcs).Cast <AuditEntity>().ToList();
                }
                catch (Exception ex)
                {
                    throw new Exception(
                              $"Ошибка при попытке загрузить операции изменения {nameof(AuditEntity)} для объекта({obj.__PrimaryKey}). {ex.Message}");
                }

                var auditFieldsLcs = LoadingCustomizationStruct.GetSimpleStruct(typeof(AuditField), ViewForField);
                foreach (var changeEntity in changedAuditEntity)
                {
                    if (changeEntity.OperationType != OperationCreateType)
                    {
                        List <AuditField> changedFields;
                        try
                        {
                            // Загружаем набор изменившихся полей из аудита
                            auditFieldsLcs.LimitFunction =
                                FunctionBuilder.BuildEquals <AuditField>(x => x.AuditEntity, changeEntity);
                            changedFields = DataServiceFactory.AppDataService.LoadObjects(auditFieldsLcs)
                                            .Cast <AuditField>().ToList();
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(
                                      $"Произошла ошибка при попытке получить набор изменений полей для операции аудита:{PKHelper.GetGuidByObject(changeEntity)}. {ex.Message}");
                        }

                        //Берём только изменения, вспомогательные объекты LinkedPrimaryKey остаются в основном списке.
                        var onlySelfChangedFields = changedFields.Where(y => y.MainChange == null);
                        foreach (var changedField in onlySelfChangedFields)
                        {
                            var mainChange =
                                changedFields.FirstOrDefault(x => PKHelper.EQPK(x.MainChange, changedField));
                            if (mainChange == null)
                            {
                                //Если основного изменения нет, то это обычное поле
                                var propertyInfo = objType.GetProperty(changedField.Field);
                                if (propertyInfo != null)
                                {
                                    var    typeprop = propertyInfo.PropertyType;
                                    object value    = null;
                                    try
                                    {
                                        if (changedField.OldValue != null)
                                        {
                                            if (typeprop.IsEnum)
                                            {
                                                value = EnumCaption.GetValueFor(changedField.OldValue, typeprop);
                                            }
                                            else if (typeprop == typeof(NullableDateTime))
                                            {
                                                value = NullableDateTime.Parse(changedField.OldValue);
                                            }
                                            else if (typeprop == typeof(NullableInt))
                                            {
                                                value = NullableInt.Parse(changedField.OldValue);
                                            }
                                            else
                                            {
                                                value = Convert.ChangeType(changedField.OldValue, typeprop, CultureInfo.InvariantCulture);
                                            }
                                        }

                                        propertyInfo.SetValue(obj, value);
                                    }
                                    catch (Exception ex)
                                    {
                                        var errorText = value != null
                                            ? $"AuditField:{PKHelper.GetGuidByObject(changedField)} Ошибка при попытке установить значение поля {value} в объект {objType.Name}:{PKHelper.GetGuidByObject(obj)} поле {changedField.Field}"
                                            : $"AuditField:{PKHelper.GetGuidByObject(changedField)} Ошибка при попытке преобразовать значение поля {changedField.OldValue} в тип {typeprop.Name}";
                                        throw new Exception($"{errorText}. {ex.Message}");
                                    }
                                }
                                else
                                {
                                    throw new Exception(
                                              $"Ошибка - не найдено поле {changedField.Field} в объекте {objType.Name}.");
                                }
                            }
                            else
                            {
                                // Есть основное изменение, значит это изменение ссылочного объекта.
                                // Только если изменилась ссылка
                                if (mainChange.OldValue != mainChange.NewValue)
                                {
                                    // В аудите детейл отличается от мастера тем, что у него приписывается в скобках позиция
                                    if (Regex.IsMatch(changedField.Field, "[ ][(][0-9]+[)]$"))
                                    {
                                        // Это изменение детейла объекта.
                                        var separateIndex       = changedField.Field.IndexOf(" ", StringComparison.Ordinal);
                                        var detailNameFromField = changedField.Field.Substring(0, separateIndex);
                                        var propertyInfo        = objType.GetProperty(detailNameFromField);
                                        if (propertyInfo != null)
                                        {
                                            if (propertyInfo.GetValue(obj) is DetailArray detailValue)
                                            {
                                                if (changedField.OldValue == "-NULL-")
                                                {
                                                    var key = new KeyGuid(mainChange.NewValue);
                                                    try
                                                    {
                                                        detailValue.RemoveByKey(key);
                                                    }
                                                    catch (Exception ex)
                                                    {
                                                        throw new Exception(
                                                                  $"Ошибка при попытке удалить объект с ключом {key} из детейла {detailNameFromField} в объекте {objType.Name}. {ex.Message}");
                                                    }
                                                }
                                                else
                                                {
                                                    var detailItemType = detailValue.ItemType;
                                                    var oldDetailObj   = Helper.CreateDataObject(detailItemType,
                                                                                                 mainChange.OldValue);
                                                    try
                                                    {
                                                        detailValue.AddObject(oldDetailObj);
                                                    }
                                                    catch (Exception ex)
                                                    {
                                                        throw new Exception(
                                                                  $"Ошибка при добавить объект с ключом {PKHelper.GetGuidByObject(oldDetailObj)} в детейл {detailNameFromField} в объекте {objType.Name}. {ex.Message}");
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            throw new Exception(
                                                      $"Ошибка - не найден детейл {detailNameFromField} в объекте {objType.Name}.");
                                        }
                                    }
                                    else
                                    {
                                        // Это изменение мастера объекта.
                                        var propertyInfo = objType.GetProperty(changedField.Field);
                                        if (propertyInfo != null)
                                        {
                                            //Это свойство является агрегатором, для детейла
                                            var itIsAgregator =
                                                propertyInfo.GetCustomAttribute <AgregatorAttribute>() != null;
                                            if (changedField.OldValue == "-NULL-" ||
                                                forceNullAgregator && itIsAgregator)
                                            {
                                                //Если свойство является агрегатором для детейла, то в последующих витках рекурсии всегда возвращаем нулл для такого поля, во избежание циклических ссылок.
                                                propertyInfo.SetValue(obj, null);
                                            }
                                            else
                                            {
                                                var typeprop     = propertyInfo.PropertyType;
                                                var oldMasterObj =
                                                    Helper.CreateDataObject(typeprop, mainChange.OldValue);
                                                try
                                                {
                                                    propertyInfo.SetValue(obj, oldMasterObj);
                                                }
                                                catch (Exception ex)
                                                {
                                                    throw new Exception(
                                                              $"Ошибка при попытке установить свойство мастера {changedField.Field} в объекте {objType.Name}. {ex.Message}");
                                                }
                                            }
                                        }
                                        else
                                        {
                                            throw new Exception(
                                                      $"Ошибка - не найден мастер {changedField.Field} в объекте {objType.Name}.");
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // Если откатываем создание объекта, то возвращаем путой объект с первичным ключом.
                        obj = Helper.CreateDataObject(objType, obj.__PrimaryKey);
                    }
                }

                // На этом этапе основной объект и все его собственные поля и зависимые сущности возвращены на дату
                // Получаем мастера и откатываем их поля, рекурсивно вызывая этот метод
                // Получаем детейлы объекта и откатываем их поля, рекурсивно вызывая этот метод
                if (!onlySelfObj && changedAuditEntity.Any())
                {
                    var objProperties = objType.GetProperties();
                    foreach (var property in objProperties)
                    {
                        var typeprop = property.PropertyType;
                        if (typeprop.IsSubclassOf(typeof(DataObject)))
                        {
                            //Перебираем все мастера
                            var masterValue = property.GetValue(obj) as DataObject;
                            GetObjForDate(date, ref masterValue, false, true);
                        }
                        else if (typeprop.IsSubclassOf(typeof(DetailArray)))
                        {
                            //Перебираем все детейлы
                            if (property.GetValue(obj) is DetailArray detailValue)
                            {
                                var detailObjects = detailValue.GetAllObjects();
                                foreach (var dataObject in detailObjects)
                                {
                                    var currentObj = dataObject;
                                    GetObjForDate(date, ref currentObj, false, true);
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #15
0
        /// <summary>
        ///     Обработка объекта
        /// </summary>
        /// <param name="obj">объект, который пришел</param>
        /// <param name="state">тип изменения, входящего объекта</param>
        /// <param name="type">тип объекта, в который преобразуем</param>
        /// <param name="mapper">маппер для преобразования</param>
        /// <param name="attrs">список изменяемых свойств</param>
        /// <param name="source">Источник изменений</param>
        /// <param name="arrToUpd">Список обновляемых объектов данных</param>
        /// <param name="arrConformity">Список обновляемых объектов синхронизации</param>
        private void ProcessObject(SyncXMLDataObject obj, tState state, Type type,
                                   IPropertyMapperWithChangedAttrs mapper, List <string> attrs, Source source, ref List <DataObject> arrToUpd,
                                   ref Dictionary <string, List <DataObject> > arrConformity)
        {
            if (obj == null)
            {
                return;
            }

            var view     = mapper.GetView();
            var nameType = type.FullName;

            var otype = arrConformity[sObjectType].Cast <ObjectType>().FirstOrDefault(x => x.name == nameType) ??
                        _syncDS.Query <ObjectType>(ObjectType.Views.ObjectTypeE)
                        .FirstOrDefault(x => x.name == nameType) ??
                        new ObjectType {
                name = nameType, id = type.Name
            };

            if (otype.GetStatus() == ObjectStatus.Created)
            {
                arrConformity[sObjectType].Add(otype);
            }

            Conformity conformity = null;

            if (otype.GetStatus() != ObjectStatus.Created && source.GetStatus() != ObjectStatus.Created)
            {
                conformity = _syncDS.Query <Conformity>(Conformity.Views.ConformityE).FirstOrDefault(x =>
                                                                                                     x.Source.__PrimaryKey.Equals(source.__PrimaryKey) &&
                                                                                                     x.Type.__PrimaryKey.Equals(otype.__PrimaryKey) && x.pkSource.Equals(obj.Guid));
            }

            if (state != tState.deleted) //создание/изменение
            {
                DataObject dest = null;
                if (conformity != null) //ищем по pk
                {
                    dest = GetDataObject(type, view, conformity.pkDest);
                }
                else
                {
                    dest = GetDataObject(type, view, obj.Guid);
                }

                if (dest == null) //ищем по альтернативному ключу
                {
                    var queryAlt = mapper.GetAltKey(obj, _defDS, _syncDS, source, ref arrToUpd, ref arrConformity);
                    dest = queryAlt?.FirstOrDefault();

                    if (queryAlt != null && dest != null)
                    {
                        LogService.LogInfo($"BusMessageHandlerService: Удалось найти объект(pk-{obj.Guid}) по альтернативному ключу для типа {nameType}. Сопоставленный объект объект(pk-{dest.__PrimaryKey})");
                    }
                }

                if (dest == null)
                {
                    dest = (DataObject)Activator.CreateInstance(type);
                }

                dest.GetStatus();

                dest = mapper.Map(obj, dest, attrs);

                // Проверяем было ли помещено создание объекта на апдейт. Если да, то такой объект уже считается существующим и статус нового объекта с таким же ключом меняется на Altered.
                var alreadyExistsCreatedObj = arrToUpd.Exists(x => PKHelper.EQPK(x, dest) && x.GetStatus(false) == ObjectStatus.Created);
                if (alreadyExistsCreatedObj)
                {
                    dest.SetLoadingState(LoadingState.Loaded);
                    dest.SetStatus(ObjectStatus.Altered);
                }
                arrToUpd.Add(dest);
                //заполнение мастеров///////////////////////////////////////////////////////////////////////////////
                mapper.SetMasters(obj, dest, attrs, _defDS, _syncDS, source, ref arrToUpd, ref arrConformity);
                if (conformity == null)
                {
                    conformity = new Conformity
                    {
                        Source   = source,
                        Type     = otype,
                        pkSource = obj.Guid,
                        pkDest   = new Guid(dest.__PrimaryKey.ToString())
                    };
                    arrConformity[sConformity].Add(conformity);
                }
            }
            else //удаление
            {
                if (conformity != null)
                {
                    var count = _syncDS.Query <Conformity>(Conformity.Views.ConformityE).Count(x =>
                                                                                               x.Type.__PrimaryKey.Equals(otype.__PrimaryKey) &&
                                                                                               x.pkDest.Equals(conformity.pkDest));
                    if (count >= 1)
                    {
                        conformity.SetStatus(ObjectStatus.Deleted);
                        arrConformity[sConformity].Add(conformity);
                    }

                    if (count == 1)
                    {
                        var dest = GetDataObject(type, view, conformity.pkDest);
                        if (dest != null)
                        {
                            dest.SetStatus(ObjectStatus.Deleted);
                            arrToUpd.Add(dest);
                        }
                    }
                }
            }
        }