//No setea valores null
        //Si se modifico la pk aunque sea natural no la updatea (usea ignora la pk)
        private void update(Serializable objeto, String primaryKeyPropertyName, String tableName, bool cascadeMode)
        {
            String updateQuery = "update " + tableName + " set ";

            List <SqlParameter> parametros = new List <SqlParameter>();

            Dictionary <string, object> propertyValues = getPropertyValues(objeto);

            foreach (KeyValuePair <string, object> keyValuePair in propertyValues)
            {
                if (keyValuePair.Key != primaryKeyPropertyName)
                {
                    String dataName = objeto.getMapFromKey(keyValuePair.Key);

                    if (dataName != "")
                    {
                        bool isSerializableProperty = typeof(Serializable).IsAssignableFrom(keyValuePair.Value.GetType());

                        object parametro = keyValuePair.Value;

                        if (isSerializableProperty)
                        {
                            Serializable serializableProperty = (Serializable)keyValuePair.Value;

                            parametro = serializableProperty.getPropertyValue(serializableProperty.getIdPropertyName());
                        }
                        updateQuery += dataName + "=@" + dataName + ",";
                        DataBase.Instance.agregarParametro(parametros, "@" + dataName, parametro);
                    }
                }
            }

            updateQuery = updateQuery.Remove(updateQuery.Length - 1);

            updateQuery += " where " + objeto.getMapFromKey(primaryKeyPropertyName) + "="
                           + objeto.getPkValue();

            if (cascadeMode)
            {
                List <String> serializablePropertyNames = listSerializableProperties(objeto);

                foreach (KeyValuePair <string, object> keyValuePair in propertyValues)
                {
                    //Aca supongo que no puede ser null
                    if (serializablePropertyNames.Contains(keyValuePair.Key))
                    {
                        Serializable serializableProperty = (Serializable)keyValuePair.Value;

                        update(serializableProperty, serializableProperty.getIdPropertyName(), serializableProperty.getTableName(), cascadeMode);
                    }
                }
            }

            DataBase.Instance.ejecutarConsulta(updateQuery, parametros);

            foreach (var item in objeto.getOneToManyPropertyNames())
            {
                updateOneToManyProperty(objeto, item, cascadeMode);
            }
        }
        private object selectById(object id, Type classType)
        {
            Serializable objeto = (Serializable)Activator.CreateInstance(classType);

            IList result = selectByProperty(objeto.getIdPropertyName(), id, classType);

            return((result.Count > 0) ? result[0] : null);
        }
        private void createOneToManyTables(Serializable objeto)
        {
            foreach (var item in objeto.getOneToManyPropertyNames())
            {
                string tableName = objeto.getOneToManyTable(item);

                if (!existsTable(tableName))
                {
                    createOneToManyTable(objeto, item);
                }
                else
                {
                    addOneToManyForeignKey(objeto.getMapFromKey(objeto.getIdPropertyName()),
                                           tableName, objeto.getTableName(),
                                           objeto.getOneToManyPk(item),
                                           objeto.getPropertyType(objeto.getIdPropertyName()));
                }
            }
        }
        private void completeOneToManyProperty(Serializable incompleteObject, string propertyName)
        {
            Type containingTypeOfProperty = incompleteObject.getOneToManyPropertyType(propertyName);

            Serializable containingTypeOfPropertyInstance = (Serializable)Activator.CreateInstance(containingTypeOfProperty);

            string intermediateTable = incompleteObject.getOneToManyTable(propertyName);
            string currentForeignKey = incompleteObject.getOneToManyFk(propertyName);
            string currentPrimaryKey = incompleteObject.getOneToManyPk(propertyName);

            object currentIdValue = incompleteObject.getPkValue();

            string expected = "@" + currentPrimaryKey;
            List <SqlParameter> sqlParameters = new List <SqlParameter>();

            DataBase.Instance.agregarParametro(sqlParameters, expected, currentIdValue);

            string query          = "select * from " + intermediateTable + " ";
            string conditionQuery = "where " + currentPrimaryKey + "=" + expected;

            if (containingTypeOfPropertyInstance.getTableName() != intermediateTable)
            {
                query += "inner join " + containingTypeOfPropertyInstance.getTableName() +
                         " on(" + intermediateTable + "." + currentForeignKey + "=" +
                         containingTypeOfPropertyInstance.getTableName() + "." +
                         containingTypeOfPropertyInstance.
                         getMapFromKey(containingTypeOfPropertyInstance.getIdPropertyName()) + ") ";
            }

            query += conditionQuery;

            Type listType = incompleteObject.getPropertyType(propertyName);

            object dummyList = Activator.CreateInstance(listType);

            //Asigno una lista vacia a la propiedad
            incompleteObject.GetType().GetProperty(propertyName).
            SetValue(incompleteObject, dummyList);

            foreach (var item in executeQuery(query, sqlParameters, containingTypeOfProperty))
            {
                List <object> parameters = new List <object> {
                    item
                };
                incompleteObject.GetType().GetProperty(propertyName).
                PropertyType.GetMethod("Add").
                Invoke(incompleteObject.getPropertyValue(propertyName), parameters.ToArray());
            }
        }
        private object unSerialize(Dictionary <string, object> dictionary, Type modelClassType)
        {
            Serializable objeto = (Serializable)Activator.CreateInstance(modelClassType);

            Dictionary <string, object> dictionaryAux = copyDictionary(dictionary);

            foreach (String dataName in dictionary.Keys)
            {
                String propertyName = objeto.getMapFromVal(dataName);
                String keyToRemove  = dataName;

                if (propertyName != "")
                {
                    Type propertyType = objeto.getPropertyType(propertyName);

                    bool isSerializable = typeof(Serializable).IsAssignableFrom(propertyType);

                    if (dictionary[dataName].ToString() != "")//Esto esta hardcodeado para que no setee cosas en null
                    {
                        if (isSerializable)
                        {
                            Serializable propertyInstance = (Serializable)Activator.CreateInstance(propertyType);
                            keyToRemove = propertyInstance.getMapFromKey(propertyInstance.getIdPropertyName());

                            object dataValue = dictionaryAux[dataName];
                            dictionaryAux.Remove(dataName);

                            if (!dictionaryAux.ContainsKey(keyToRemove))//parchado porque rompio en un test diciendo que ya se habia insertado la clave
                            {
                                dictionaryAux.Add(keyToRemove, dataValue);
                            }

                            objeto.GetType().GetProperty(propertyName).SetValue(objeto, unSerialize(dictionaryAux, propertyType));
                        }

                        else
                        {
                            object dataValue = getCastedValue(dictionary[dataName], objeto.getPropertyType(propertyName));
                            objeto.GetType().GetProperty(propertyName).SetValue(objeto, dataValue);
                        }
                        dictionaryAux.Remove(keyToRemove);
                    }
                }
            }

            return(objeto);
        }
        private void insertOneToManyProperty(Serializable objeto, string propertyName, bool cascade)
        {
            Type propertyType = objeto.getOneToManyPropertyType(propertyName);

            string propertyTable = ((Serializable)Activator.CreateInstance(propertyType)).getTableName();

            string oneToManyTable = objeto.getOneToManyTable(propertyName);

            string expectedPk = "@" + objeto.getOneToManyPk(propertyName);

            foreach (var item in (IEnumerable)objeto.getPropertyValue(propertyName))
            {
                Serializable serializableItem = (Serializable)item;

                string expectedFk = "@" + objeto.getOneToManyFk(propertyName);

                List <SqlParameter> sqlParameters = new List <SqlParameter>();
                DataBase.Instance.agregarParametro(sqlParameters, expectedPk, objeto.getPkValue());
                DataBase.Instance.agregarParametro(sqlParameters, expectedFk, serializableItem.getPkValue());

                string query = "";

                if (propertyTable == oneToManyTable)
                {
                    if (cascade)
                    {
                        insert(serializableItem, serializableItem.getIdPropertyName(), propertyTable, cascade);
                    }

                    query = "update " + propertyTable + " set " + objeto.getOneToManyPk(propertyName) + "=" + expectedPk +
                            "where " + objeto.getOneToManyFk(propertyName) + "=" + expectedFk;
                }
                else
                {
                    query = "insert into " + oneToManyTable + "(" + objeto.getOneToManyPk(propertyName) +
                            "," + objeto.getOneToManyFk(propertyName) + ") values(" + expectedPk + "," +
                            expectedFk + ")";
                }

                DataBase.Instance.ejecutarConsulta(query, sqlParameters);
            }
        }
        private void createIncompleteTable(Serializable objeto)
        {
            if (existsTable(objeto.getTableName()))
            {
                return;
            }

            string createQuery = "create table " + objeto.getTableName() + "(";

            foreach (var item in listProperties(objeto))
            {
                if (!isSerializableProperty(item, objeto))
                {
                    String dataType = getDataTypeName(getPropertyType(item, objeto));

                    if (dataType != "" && objeto.getMapFromKey(item) != "")
                    {
                        createQuery += objeto.getMapFromKey(item) + " " + dataType;

                        if (objeto.getIdPropertyName() == item)
                        {
                            createQuery += " not null primary key";

                            if (objeto.getPrimaryKeyType() == PrimaryKeyType.SURROGATE)
                            {
                                createQuery += " identity(1,1)";
                            }
                        }

                        createQuery += ",";
                    }
                }
            }

            createQuery  = createQuery.Remove(createQuery.Length - 1);
            createQuery += ")";

            DataBase.Instance.ejecutarConsulta(createQuery);
        }
        private void createOneToManyTable(Serializable objeto, string propertyName)
        {
            Type containingTypeOfProperty = objeto.getOneToManyPropertyType(propertyName);

            Serializable containingTypeOfPropertyInstance = (Serializable)Activator.CreateInstance(containingTypeOfProperty);

            string pkName    = objeto.getOneToManyPk(propertyName);
            string tableName = objeto.getOneToManyTable(propertyName);
            string fkName    = objeto.getOneToManyFk(propertyName);

            string pkDataTypeName = getDataTypeName(objeto.GetType().
                                                    GetProperty(objeto.getIdPropertyName()).PropertyType);

            string fkDataTypeName = getDataTypeName(containingTypeOfPropertyInstance.GetType().
                                                    GetProperty(containingTypeOfPropertyInstance.
                                                                getIdPropertyName()).PropertyType);

            string createQuery = "create table " + tableName + "(" + pkName + " " +
                                 pkDataTypeName + " ," + fkName + " " + fkDataTypeName + ", " +
                                 "primary key(" + pkName + "," + fkName + "))";

            DataBase.Instance.ejecutarConsulta(createQuery);
        }
 internal void updateCascade(Serializable objeto)
 {
     update(objeto, objeto.getIdPropertyName(), objeto.getTableName(), true);
 }
 internal void update(Serializable objeto)
 {
     update(objeto, objeto.getIdPropertyName(), objeto.getTableName(), false);
 }
 internal void delete(Serializable objeto)
 {
     delete(objeto, objeto.getIdPropertyName(), objeto.getTableName());
 }
        private void insert(Serializable objeto, String primaryKeyPropertyName, String tableName, bool cascade)
        {
            String insertQuery = "insert into " + tableName + "(";

            String valuesString = " values (";

            List <SqlParameter> parametros = new List <SqlParameter>();

            Dictionary <string, object> propertyValues = getPropertyValues(objeto);

            foreach (KeyValuePair <string, object> keyValuePair in propertyValues)
            {
                if (keyValuePair.Key != primaryKeyPropertyName || objeto.getPrimaryKeyType() == PrimaryKeyType.NATURAL)
                {
                    String dataName = objeto.getMapFromKey(keyValuePair.Key);

                    if (dataName != "")
                    {
                        insertQuery += dataName + ",";

                        valuesString += "@" + dataName + ",";

                        bool isSerializableProperty = typeof(Serializable).IsAssignableFrom(keyValuePair.Value.GetType());

                        Serializable serializableProperty = isSerializableProperty ? (Serializable)keyValuePair.Value : null;

                        if (cascade && isSerializableProperty)
                        {
                            insert(serializableProperty, serializableProperty.getIdPropertyName(), serializableProperty.getTableName(), true);
                        }

                        object parametro = isSerializableProperty ? serializableProperty.getPropertyValue(
                            serializableProperty.getIdPropertyName()) : keyValuePair.Value;

                        DataBase.Instance.agregarParametro(parametros, "@" + dataName, parametro);
                    }
                }
            }

            string primaryKeyName = objeto.getMapFromKey(objeto.getIdPropertyName());

            insertQuery  = insertQuery.Remove(insertQuery.Length - 1);
            valuesString = valuesString.Remove(valuesString.Length - 1);
            insertQuery += ") " + "output inserted." + primaryKeyName
                           + valuesString + ")";

            object insertResult = DataBase.Instance.ejecutarConsulta(
                insertQuery, parametros)[0][primaryKeyName];

            Type idType = objeto.getPropertyType(objeto.getIdPropertyName());

            object idValue = null;

            if (typeof(Serializable).IsAssignableFrom(idType))
            {
                idValue = objeto.getIdValue();
                Serializable serializableId = (Serializable)idValue;
                serializableId.GetType().GetProperty(serializableId.getIdPropertyName()).
                SetValue(serializableId,
                         getCastedValue(insertResult,
                                        serializableId.
                                        getPropertyType(serializableId.getIdPropertyName())));
            }
            else
            {
                idValue = getCastedValue(insertResult, idType);
            }

            objeto.GetType().GetProperty(objeto.getIdPropertyName()).SetValue(objeto, idValue);

            foreach (var item in objeto.getOneToManyPropertyNames())
            {
                insertOneToManyProperty(objeto, item, cascade);
            }
        }
 internal void insertCascade(Serializable objeto)
 {
     insert(objeto, objeto.getIdPropertyName(), objeto.getTableName(), true);
 }
 internal void insert(Serializable objeto)
 {
     insert(objeto, objeto.getIdPropertyName(), objeto.getTableName(), false);
 }
        private void createForeignKeys(Serializable objeto)
        {
            int serializablePropertyCounter = listProperties(objeto).Count(property =>
                                                                           isSerializableProperty(property, objeto) && objeto.getMapFromKey(property) != "");

            if (serializablePropertyCounter == 0)
            {
                return;
            }

            bool existsFkEqualToPk = listProperties(objeto).Exists(prop =>
                                                                   objeto.getMapFromKey(prop) == objeto.getMapFromKey(objeto.getIdPropertyName()) &&
                                                                   typeof(Serializable).IsAssignableFrom(getPropertyType(prop, objeto)));

            //Este es el caso en el que la pk sea una fk y que solo haya 1 fk
            if (serializablePropertyCounter == 1 && existsFkEqualToPk)
            {
                Type propertyType = getPropertyType(listProperties(objeto).Find(prop =>
                                                                                isSerializableProperty(prop, objeto)), objeto);

                Serializable property = dictionaryObjectsAndTypes[propertyType];
                DataBase.Instance.ejecutarConsulta("alter table " + objeto.getTableName() +
                                                   " add foreign key(" + objeto.getMapFromKey(objeto.getIdPropertyName()) +
                                                   ") references " + property.getTableName() + "(" +
                                                   property.getMapFromKey(property.getIdPropertyName()) + ")");

                return;
            }

            string alterQuery = "alter table " + objeto.getTableName() + " add ";

            string foreignKeys = "";

            foreach (var item in listProperties(objeto))
            {
                Type propertyType = getPropertyType(item, objeto);

                if (isSerializableProperty(item, objeto) && objeto.getMapFromKey(item) != "")
                {
                    Serializable property       = dictionaryObjectsAndTypes[propertyType];
                    Type         idPropertyType = getPropertyType(property.getIdPropertyName(), property);

                    string primaryKeyProperty = property.getMapFromKey(property.getIdPropertyName());
                    string foreignKeyProperty = objeto.getMapFromKey(item);
                    string tableNameProperty  = property.getTableName();

                    if (objeto.getMapFromKey(item) != objeto.getMapFromKey(objeto.getIdPropertyName()))//Si es la pk, ya se inserto
                    {
                        alterQuery += foreignKeyProperty + " " + getDataTypeName(idPropertyType) + ",";
                    }

                    foreignKeys += "foreign key(" + foreignKeyProperty + ") references "
                                   + tableNameProperty + "(" + primaryKeyProperty + "),";
                }
            }

            foreignKeys = foreignKeys.Remove(foreignKeys.Length - 1);
            alterQuery += foreignKeys;

            DataBase.Instance.ejecutarConsulta(alterQuery);
        }