private void SetEntityForeignKey(object parentEntity, object childEntity)
        {
            var parentProps = parentEntity.GetType().GetProperties();
            var parentKey   = EntityReflector.GetKeyColumn(parentProps);

            var childProps      = childEntity.GetType().GetProperties();
            var childForeignKey = EntityReflector.GetForeignKeyColumn(childProps);

            if ((parentKey != null) && (childForeignKey != null))
            {
                childForeignKey.SetValue(childEntity, parentKey.GetValue(parentEntity, null), null);
            }
        }
        private void CreateReplicas(object entity, PropertyInfo[] entityProps, int lastInsertedId, bool persistComposition)
        {
            var entityColumnKey = EntityReflector.GetKeyColumn(entityProps);

            if (entityColumnKey != null)
            {
                entityColumnKey.SetValue(entity, lastInsertedId, null);
            }

            ParallelParam parallelParam = new ParallelParam()
            {
                Param1 = entity,
                Param2 = PersistenceAction.Create,
                Param3 = persistComposition
            };

            var replicationParallelDelegate = new ParameterizedThreadStart(PersistReplicasAsync);

            Parallelizer.StartNewProcess(replicationParallelDelegate, parallelParam);
        }
        private List <string> ParseComposition(object entity, PersistenceAction action, object filterEntity)
        {
            List <string> result = new List <string>();
            object        childEntityInstance = null;

            var entityType = entity.GetType();
            IEnumerable <PropertyInfo> childEntities = entityType.GetProperties().Where(prp => prp.GetCustomAttributes(true)
                                                                                        .Any(atb => atb.GetType().Name.Equals("RelatedEntity")));

            foreach (PropertyInfo child in childEntities)
            {
                var relationAttrib = child.GetCustomAttributes(true)
                                     .FirstOrDefault(atb => atb.GetType().Name.Equals("RelatedEntity")) as RelatedEntity;

                childEntityInstance = child.GetValue(entity, null);
                object childEntityFilter = null;

                var entityParent = (action != PersistenceAction.Edit) ? entity : filterEntity;

                if (childEntityInstance != null)
                {
                    var childEntityType = childEntityInstance.GetType();

                    if (!childEntityType.Name.Contains("List"))
                    {
                        var childProps = childEntityType.GetProperties();
                        action            = EntitySqlParser.SetPersistenceAction(childEntityInstance, EntityReflector.GetKeyColumn(childProps));
                        childEntityFilter = Activator.CreateInstance(childEntityInstance.GetType());

                        if (action == PersistenceAction.Edit)
                        {
                            EntityReflector.MigrateEntityPrimaryKey(childEntityInstance, childProps, childEntityFilter);
                        }

                        SetEntityForeignKey(entityParent, child);

                        result.Add(EntitySqlParser.ParseEntity(childEntityInstance, engine, action));
                    }
                    else
                    {
                        var           childListInstance = (IList)childEntityInstance;
                        List <object> childFiltersList  = new List <object>();

                        if (childListInstance.Count > 0)
                        {
                            foreach (var listItem in childListInstance)
                            {
                                if (relationAttrib.Cardinality == RelationCardinality.OneToMany)
                                {
                                    var listItemType = listItem.GetType();
                                    childEntityFilter = Activator.CreateInstance(listItemType);

                                    var listItemProps = listItemType.GetProperties();
                                    action = EntitySqlParser.SetPersistenceAction(listItem, EntityReflector.GetKeyColumn(listItemProps));

                                    if (action == PersistenceAction.Edit)
                                    {
                                        EntityReflector.MigrateEntityPrimaryKey(listItem, listItemProps, childEntityFilter);
                                        childFiltersList.Add(childEntityFilter);
                                    }

                                    SetEntityForeignKey(entityParent, listItem);

                                    result.Add(EntitySqlParser.ParseEntity(listItem, engine, action));
                                }
                                else
                                {
                                    var manyToEntity = EntitySqlParser.ParseManyToRelation(listItem, relationAttrib);

                                    SetEntityForeignKey(entityParent, manyToEntity);

                                    var existRelation = this.GetObject(manyToEntity);

                                    if (existRelation != null)
                                    {
                                        manyToEntity = existRelation;
                                    }

                                    var manyToEntityProps = manyToEntity.GetType().GetProperties();
                                    action = EntitySqlParser.SetPersistenceAction(manyToEntity, EntityReflector.GetKeyColumn(manyToEntityProps));

                                    object existFilter = null;
                                    if (action == PersistenceAction.Edit)
                                    {
                                        existFilter = Activator.CreateInstance(manyToEntity.GetType());
                                        EntityReflector.MigrateEntityPrimaryKey(manyToEntity, manyToEntityProps, existFilter);
                                        childFiltersList.Add(existFilter);
                                    }

                                    result.Add(EntitySqlParser.ParseEntity(manyToEntity, engine, action));
                                }
                            }
                        }
                        else
                        {
                            var childInstance = Activator.CreateInstance(childListInstance.GetType().GetGenericArguments()[0]);

                            var childEntity = new object();
                            if (relationAttrib.Cardinality == RelationCardinality.ManyToMany)
                            {
                                childEntity = EntitySqlParser.ParseManyToRelation(childInstance, relationAttrib);
                            }
                            else
                            {
                                childEntity = childInstance;
                            }

                            SetEntityForeignKey(entityParent, childEntity);

                            childFiltersList.Add(childEntity);
                        }
                    }
                }
            }

            if (result.Any(rst => rst.Contains(SQLStatements.SQL_ReservedWord_INSERT)))
            {
                result.Reverse();
            }

            return(result);
        }
        private void FillComposition(object loadedEntity, PropertyInfo[] entityProps)
        {
            RelatedEntity relationConfig = null;

            var propertiesList = entityProps.Where(prp => prp.GetCustomAttributes(true)
                                                   .Any(atb => atb.GetType().Name.Equals("RelatedEntity")));

            foreach (var prop in propertiesList)
            {
                object attributeInstance = null;

                IEnumerable <object> attributeAnnotations = prop.GetCustomAttributes(true)
                                                            .Where(atb => atb.GetType().Name.Equals("RelatedEntity"));

                foreach (object annotation in attributeAnnotations)
                {
                    relationConfig = (RelatedEntity)annotation;

                    PropertyInfo foreignKeyColumn = null;
                    object       foreignKeyValue  = null;

                    var keyColumn = EntityReflector.GetKeyColumn(entityProps);

                    switch (relationConfig.Cardinality)
                    {
                    case RelationCardinality.OneToOne:

                        attributeInstance = Activator.CreateInstance(prop.PropertyType);

                        foreignKeyColumn = loadedEntity.GetType().GetProperty(relationConfig.ForeignKeyAttribute);

                        foreignKeyValue = foreignKeyColumn.GetValue(loadedEntity, null);

                        if ((foreignKeyValue != null) && int.Parse(foreignKeyValue.ToString()) > 0)
                        {
                            var attributeProps     = attributeInstance.GetType().GetProperties();
                            var keyColumnAttribute = EntityReflector.GetKeyColumn(attributeProps);

                            keyColumnAttribute.SetValue(attributeInstance, foreignKeyColumn.GetValue(loadedEntity, null), null);

                            attributeInstance = GetObject(attributeInstance);
                        }

                        break;

                    case RelationCardinality.OneToMany:

                        attributeInstance = Activator.CreateInstance(prop.PropertyType.GetGenericArguments()[0], true);

                        foreignKeyColumn = attributeInstance.GetType().GetProperty(relationConfig.ForeignKeyAttribute);
                        foreignKeyColumn.SetValue(attributeInstance, int.Parse(keyColumn.GetValue(loadedEntity, null).ToString()), null);

                        attributeInstance = ListObjects(attributeInstance as object, PersistenceAction.List);

                        break;

                    case RelationCardinality.ManyToMany:

                        attributeInstance = Activator.CreateInstance(relationConfig.IntermediaryEntity, true);

                        if (attributeInstance != null)
                        {
                            SetEntityForeignKey(loadedEntity, attributeInstance);

                            var manyToRelations = ListObjects(attributeInstance, PersistenceAction.List, true);

                            Type  childManyType     = prop.PropertyType.GetGenericArguments()[0];
                            Type  dynamicManyType   = typeof(List <>).MakeGenericType(new Type[] { childManyType });
                            IList childManyEntities = (IList)Activator.CreateInstance(dynamicManyType, true);

                            foreach (var rel in manyToRelations)
                            {
                                var childManyKeyValue = rel.GetType().GetProperty(relationConfig.IntermediaryKeyAttribute).GetValue(rel, null);
                                var childFilter       = Activator.CreateInstance(childManyType);

                                var childFilterProps = childFilter.GetType().GetProperties();
                                EntityReflector.GetKeyColumn(childFilterProps).SetValue(childFilter, childManyKeyValue, null);

                                var childInstance = GetObject(childFilter);

                                childManyEntities.Add(childInstance);
                            }

                            attributeInstance = childManyEntities;
                        }
                        break;
                    }
                }

                if (attributeInstance != null)
                {
                    if (!prop.PropertyType.Name.Contains("List"))
                    {
                        prop.SetValue(loadedEntity, attributeInstance, null);
                    }
                    else
                    {
                        prop.SetValue(loadedEntity, (IList)attributeInstance, null);
                    }
                }
            }
        }