private static void UpdateCacheTree(int typeKeyCode, object cacheItem, bool removeItem = false)
        {
            if (!(cacheItem is IList))
            {
                var typeCacheItems = cacheItems.Where(itm => itm.Key.Key.Equals(typeKeyCode)).ToList();
                var itemProps      = cacheItem.GetType().GetProperties();
                var itemKeyId      = EntityReflector.GetKeyColumn(itemProps).GetValue(cacheItem, null);

                for (var typeCount = 0; typeCount < typeCacheItems.Count; typeCount++)
                {
                    if (!removeItem)
                    {
                        var listValue = typeCacheItems[typeCount].Value as IList;

                        if (listValue != null)
                        {
                            for (int valueCount = 0; valueCount < ((IList)typeCacheItems[typeCount].Value).Count; valueCount++)
                            {
                                if (EntityReflector.MatchKeys(cacheItem, itemProps, listValue[valueCount]))
                                {
                                    listValue[valueCount] = cacheItem;
                                }
                            }
                        }
                    }
                    else
                    {
                        cacheItems.Remove(typeCacheItems[typeCount].Key);
                    }
                }
            }
        }
        public static object ParseManyToRelation(object childEntity, RelatedEntity relation)
        {
            object result    = null;
            var    relEntity = relation.IntermediaryEntity;

            if (relEntity != null)
            {
                var interEntity = Activator.CreateInstance(relation.IntermediaryEntity);

                var childProps     = childEntity.GetType().GetProperties();
                var childKey       = EntityReflector.GetKeyColumn(childProps);
                var interKeyAttrib = interEntity.GetType().GetProperties()
                                     .FirstOrDefault(atb => atb.Name.Equals(relation.IntermediaryKeyAttribute));

                interKeyAttrib.SetValue(interEntity, childKey.GetValue(childEntity, null), null);

                result = interEntity;
            }

            return(result);
        }
        /// <summary>
        /// Parse entity model object instance to SQL ANSI CRUD statements
        /// </summary>
        /// <param name="entity">Entity model class reference</param>
        /// <param name="persistenceAction">Persistence action enum (Get, List, Create, Edit, Delete)</param>
        /// <param name="filterEntity">Filter entity model class reference</param>
        /// <param name="recordLimit">Result records limit</param>
        /// <param name="onlyListableAttributes">Flag to return only attributes marked as listable</param>
        /// <param name="showAttributes">Comma separeted list of custom object attributes to show</param>
        /// <param name="rangeValues"></param>
        /// <param name="groupAttributes">List of object attributes to group results</param>
        /// <param name="orderAttributes">List of object attributes to sort results</param>
        /// <param name="orderDescending">Flag to return ordering with descending order</param>
        /// <param name="readUncommited">Flag to return uncommited transaction queries statements (NOLOCK)</param>
        /// <returns></returns>
        public static string ParseEntity(object entity, DatabaseEngine engine, PersistenceAction persistenceAction, object filterEntity = null, int recordLimit = 0, bool onlyListableAttributes = false, string showAttributes = null, IDictionary <string, double[]> rangeValues = null, string groupAttributes = null, string orderAttributes = null, bool orderDescending = false, bool readUncommited = false)
        {
            try
            {
                string   sqlInstruction;
                string[] displayAttributes = new string[0];
                Dictionary <object, object> attributeColumnRelation;

                var entityType      = entity.GetType();
                var nameSpacePrefix = entityType.Namespace.Substring(0, entityType.Namespace.IndexOf("."));

                var entityProps = entityType.GetProperties()
                                  .Where(p => !p.PropertyType.Namespace.StartsWith(nameSpacePrefix)).ToArray();

                // Model validation
                if (!EntityReflector.VerifyTableAnnotation(entityType))
                {
                    throw new InvalidOperationException("Entity table annotation not found. Please review model definition.");
                }

                if (EntityReflector.GetKeyColumn(entityProps) == null)
                {
                    throw new KeyNotFoundException("Entity key column annotation not found. Please review model definition.");
                }
                //

                if (onlyListableAttributes)
                {
                    EntityReflector.ValidateListableAttributes(entityProps, showAttributes, out displayAttributes);
                }

                sqlInstruction = GetSqlInstruction(entity, entityType, entityProps, engine, persistenceAction, filterEntity,
                                                   recordLimit, displayAttributes, rangeValues, groupAttributes, readUncommited);

                sqlInstruction = string.Format(sqlInstruction, ((engine != DatabaseEngine.SQLServer) && (recordLimit > 0))
                               ? string.Format(SQLStatements.SQL_Action_LimitResult_MySQL, recordLimit)
                               : string.Empty, "{0}", "{1}");

                attributeColumnRelation = EntityReflector.GetPropertiesValueList(entity, entityType, entityProps, persistenceAction);

                if (!string.IsNullOrEmpty(groupAttributes))
                {
                    ParseGroupingAttributes(attributeColumnRelation, groupAttributes, ref sqlInstruction);
                }
                else
                {
                    sqlInstruction = string.Format(sqlInstruction, string.Empty, "{0}");
                }

                if (!string.IsNullOrEmpty(orderAttributes))
                {
                    ParseOrdinationAttributes(attributeColumnRelation, orderAttributes, orderDescending, ref sqlInstruction);
                }
                else
                {
                    sqlInstruction = string.Format(sqlInstruction, string.Empty);
                }

                return(sqlInstruction);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private static string GetSqlInstruction(object entity, Type entityType, PropertyInfo[] entityProps, DatabaseEngine engine, PersistenceAction action, object filterEntity, int recordLimit, string[] showAttributes, IDictionary <string, double[]> rangeValues, string groupAttributes, bool readUncommited = false)
        {
            string sqlInstruction;
            Dictionary <object, object> sqlFilterData;
            Dictionary <object, object> sqlEntityData = EntityReflector.GetPropertiesValueList(entity, entityType, entityProps, action);

            if (filterEntity != null)
            {
                sqlFilterData = EntityReflector.GetPropertiesValueList(filterEntity, entityType, entityProps, action);
            }
            else
            {
                sqlFilterData = null;
            }

            var keyColumnName = EntityReflector.GetKeyColumnName(entityProps);

            Dictionary <string, string> sqlParameters = GetSqlParameters(sqlEntityData, engine, action, sqlFilterData,
                                                                         recordLimit, showAttributes, keyColumnName,
                                                                         rangeValues, groupAttributes, readUncommited);

            switch (action)
            {
            case PersistenceAction.Create:

                sqlInstruction = String.Format(SQLStatements.SQL_Action_Create,
                                               sqlParameters["TableName"],
                                               sqlParameters["ColumnList"],
                                               sqlParameters["ValueList"]);

                break;

            case PersistenceAction.Edit:

                sqlInstruction = String.Format(SQLStatements.SQL_Action_Edit,
                                               sqlParameters["TableName"],
                                               sqlParameters["ColumnValueList"],
                                               sqlParameters["ColumnFilterList"]);

                break;

            case PersistenceAction.Delete:

                sqlInstruction = String.Format(SQLStatements.SQL_Action_Delete,
                                               sqlParameters["TableName"],
                                               sqlParameters["ColumnFilterList"]);

                break;

            default:     // Listagem ou Consulta

                sqlInstruction = String.Format(SQLStatements.SQL_Action_Query,
                                               sqlParameters["ColumnList"],
                                               sqlParameters["TableName"],
                                               sqlParameters["RelationList"],
                                               sqlParameters["ColumnFilterList"],
                                               "{0}", "{1}", string.Empty);

                break;
            }

            return(sqlInstruction);
        }