Exemplo n.º 1
0
        public static string ConvertNullableSQLToCSharp(string sqlTypeCode, bool isNullable)
        {
            string typeCode = TypeConvertor.ConvertSQLToCSharp(sqlTypeCode);

            if (isNullable && typeCode != "string")
            {
                typeCode += "?";
            }
            return(typeCode);
        }
Exemplo n.º 2
0
        private static void AddMember(ModelDef modelDef, string memberName, Type type, string requiredNamespace)
        {
            string typeCode      = type.Name;
            string typeNamespace = type.Namespace;

            if (type.Namespace != requiredNamespace)
            {
                string vernacularCode = TypeConvertor.ConvertCLRToVernacular(type.ToString());
                if (vernacularCode != null)
                {
                    typeCode      = vernacularCode;
                    typeNamespace = null;
                }
            }

            /* TODO: better to use IsClass or IsByRef ? */
            bool isReference = type.IsClass || type.IsInterface;

            if (memberName == "State")
            {
                Shared.Info("State");
            }
            if (typeCode == "string")
            {
                isReference = false;
            }



            /* TODO: not sure if this should rewrite the type here or not */
            /* TODO: the Interface rewriting should be an option */
            if (type.IsInterface && typeCode.StartsWith("I"))
            {
                typeCode = typeCode.Substring(1);
            }

            PropertyDef propertyDef = new PropertyDef {
                PropertyName          = memberName,
                PropertyTypeCode      = typeCode,
                PropertyTypeNamespace = typeNamespace,
                IsInterface           = type.IsInterface,
                IsReference           = isReference,
                IsEnum = type.IsEnum
            };

            modelDef.PropertyDefMap[memberName] = propertyDef;
        }
        /* TODO: GetSchemaTable was failing on SQL Server Express, not sure why.
         *      It's not that it needed data rows in the table.
         *      Does it need data actually returned? */
        private void PopulateFields2008(ProcedureDef procedureDef)
        {
            /* MSSQL prior to 2012 might need this, we can verify if there's a client to test against at some point */

            /*
             * call the procedure to see the result set
             *
             */



            using (SqlTransaction trans = this.SqlConnection.BeginTransaction()) {
                using (SqlCommand command = new SqlCommand()
                {
                    CommandText = procedureDef.ProcedureName,
                    CommandType = CommandType.StoredProcedure,
                    Connection = this.SqlConnection,
                    Transaction = trans
                }) {
                    foreach (ParameterDef parameterDef in procedureDef.ParameterDefMap.Values)
                    {
                        ParameterDirection direction;
                        if (parameterDef.IsOutParameter)
                        {
                            direction = ParameterDirection.Output;
                        }
                        else
                        {
                            direction = ParameterDirection.Input;
                        }

                        var parameter = new SqlParameter {
                            ParameterName = parameterDef.ParameterName,
                            Direction     = direction,
                            Size          = parameterDef.ParameterSize,
                            SqlDbType     = GetSqlDbType(parameterDef.ParameterDataTypeCode)
                        };

                        parameter.Value = DBNull.Value;
                        command.Parameters.Add(parameter);
                    }

                    DataTable tableSchema;

                    /* we really want all 3 behaviors, and within a transaction, but the two
                     * behaviors CommandBehavior.SchemaOnly and CommandBehavior.KeyInfo fail
                     * to give us a schema table to read.  So we have to get a result within
                     * a transaction.  There's nothing super wrong with that, but it feels
                     * dirty.  Here are the results of combinations we've tried (all with SQL
                     * Server Express 2014):
                     * No behaviors, no transaction : succeeded
                     * CommandBehavior.SchemaOnly alone, no transaction : failed
                     * CommandBehavior.SchemaOnly| CommandBehavior.KeyInfo, no trans : failed
                     * CommandBehavior.SchemaOnly| CommandBehavior.SingleResult, no trans : failed
                     * CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo | CommandBehavior.SingleResult, no trans : failed
                     * CommandBehavior.KeyInfo, no trans : failed
                     * CommandBehavior.KeyInfo | CommandBehavior.SingleResult, no trans : failed
                     * CommandBehavior.SingleResult, no trans : succeeded
                     * No behaviors, with trans : succeeded
                     * CommandBehavior.SingleResult, with trans : succeeded
                     */
                    using (var reader = command.ExecuteReader(CommandBehavior.SingleResult)) {
                        reader.Read();
                        tableSchema = reader.GetSchemaTable();
                    }
                    trans.Rollback();

                    if (tableSchema == null)
                    {
                        throw new ApplicationException("Sampling of procedure " + procedureDef.ProcedureName + " yielded no schema.");
                    }

                    foreach (DataRow row in tableSchema.Rows)
                    {
                        /* IsIdentity */

                        /*
                         * int columnSize = (int)row["ColumnSize"];
                         * string sqlTypeCode =
                         *      bool isReadOnly = (bool)row["IsReadOnly"];
                         * bool isPrimaryKey = (bool)row["IsKey"];
                         * bool isAutoIncrement = (bool)row["IsAutoIncrement"];
                         */

                        string fieldName = row["ColumnName"].ToString();

                        /* TODO: on views, these BaseTableName and BaseColumnName are for the view, not the source table like we get for MSSQL2012 */
                        string baseTableName  = row["BaseTableName"].ToString();
                        string baseColumnName = row["BaseColumnName"].ToString();
                        bool   isNullable     = (bool)row["AllowDBNull"];


                        string dataTypeCode = TypeConvertor.ConvertCLRToVernacular(row["DataType"].ToString());

                        FieldDef fieldDef = new FieldDef {
                            FieldName      = fieldName,
                            ProcedureDef   = procedureDef,
                            DataTypeCode   = dataTypeCode,
                            IsNullable     = isNullable,
                            BaseTableName  = baseTableName,
                            BaseColumnName = baseColumnName
                        };


                        procedureDef.FieldDefMap[fieldDef.FieldName] = fieldDef;
                    }
                }
            }
        }
        private void PopulateFields2012(ProcedureDef procedureDef)
        {
            /* pass procedureName, then a string of parameters (not necessary),
             *      browserInfo should be 0 to return only the outputted columns and not join columns
             *      and finally browserInfo must be 1 to get source table info on second call */
            var validNameList = new List <string>();

            using (SqlCommand command = new SqlCommand()
            {
                CommandText = $@"SELECT FieldName=name FROM sys.dm_exec_describe_first_result_set('{procedureDef.ProcedureName}', NULL, 0)",
                CommandType = CommandType.Text,
                Connection = this.SqlConnection
            }) {
                using (var reader = command.ExecuteReader()) {
                    while (reader.Read())
                    {
                        IDataReader row       = reader;
                        string      fieldName = row["FieldName"].ToString();
                        validNameList.Add(fieldName);
                    }
                }
            }

            using (SqlCommand command = new SqlCommand()
            {
                CommandText = $@"SELECT FieldName=name, DataTypeCode=system_type_name, IsNullable = is_nullable, BaseTableName = source_table, BaseColumnName = source_column FROM sys.dm_exec_describe_first_result_set('{procedureDef.ProcedureName}', NULL, 1)",
                CommandType = CommandType.Text,
                Connection = this.SqlConnection
            }) {
                var regex = new Regex("^(\\w+)\\(\\d+(,\\d+)?\\)$");

                using (var reader = command.ExecuteReader()) {
                    while (reader.Read())
                    {
                        IDataReader row = reader;

                        string fieldName = row["FieldName"].ToString();
                        if (fieldName == "")
                        {
                            throw new Exception("MSSQL inspection for procedure " + procedureDef.ProcedureName + " returned a field with no name.  Check the stored procedure for invalid characters.");
                        }

                        if (validNameList.Contains(fieldName) == false)
                        {
                            // Shared.Info("Skipping superfluous field " + fieldName);
                        }
                        else
                        {
                            string sqlDataTypeCode = row["DataTypeCode"].ToString();

                            /* MSSQL2012 will send a char length too, e.g. varchar(10), decimal(18,0) */
                            var match = regex.Match(sqlDataTypeCode);
                            if (match.Success)
                            {
                                sqlDataTypeCode = match.Groups[1].Value;
                            }

                            string dataTypeCode;
                            try {
                                dataTypeCode = TypeConvertor.ConvertSQLToCSharp(sqlDataTypeCode);
                            } catch {
                                Shared.Info("Call to ConvertSQLToCSharp for procedure " + procedureDef.ProcedureName + ", field named \"" + fieldName + "\", of SQL data type \"" + sqlDataTypeCode + "\".  This can happen if you have a stored procedure that is referencing a column that no longer exists for a table.  Check that the procedure will run on its own.");
                                throw;
                            }

                            bool isNullable = (bool)row["IsNullable"];
                            /* max_length, precision, scale */

                            /* TODO: using result set procedure does not populate source
                             * table or column, which is as close to these fields
                             * as I could find */
                            string baseTableName  = row["BaseTableName"].ToString();
                            string baseColumnName = row["BaseColumnName"].ToString();
                            // Shared.Info($"DEBUG:procedureName={procedureDef.ProcedureName}, fieldName={fieldName}, baseTableName={baseTableName}, baseColumnName={baseColumnName}");

                            FieldDef fieldDef = new FieldDef {
                                FieldName      = fieldName,
                                ProcedureDef   = procedureDef,
                                DataTypeCode   = dataTypeCode,
                                IsNullable     = isNullable,
                                BaseTableName  = baseTableName,
                                BaseColumnName = baseColumnName
                            };


                            procedureDef.FieldDefMap[fieldDef.FieldName] = fieldDef;
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
        public List <ProcedureDef> MakeProcedureDefList(string databaseName,
                                                        string moduleName,
                                                        Dictionary <string, TableDef> tableDefMap)
        {
            /*  var tableMap = {};
             * var functionMap = {};
             * var tableArray = [];
             *
             *
             */
            MySqlConnection conn = this.mySqlConnection;

            var globalProcedureDefMap = new Dictionary <string, ProcedureDef>();

            using (MySqlCommand command = new MySqlCommand()
            {
                CommandText = "SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA='" + databaseName
                              + "' AND ROUTINE_NAME LIKE '" + moduleName + "_%_%' AND ROUTINE_TYPE='PROCEDURE';",
                CommandType = CommandType.Text,
                Connection = conn
            }) {
                using (var reader = command.ExecuteReader()) {
                    while (reader.Read())
                    {
                        IDataRecord procRow       = reader;
                        string      procedureName = (string)procRow["ROUTINE_NAME"];

                        if ((string)procRow["SQL_DATA_ACCESS"] == "CONTAINS SQL")
                        {
                            /* TODO: I could envision a get server time function that doesn't read or write data but should be part of a DataAccess class. */
                            Shared.Info("Skipping procedure " + procedureName + " marked CONTAINS SQL, as this implies it does not read or write data.");
                        }
                        else
                        {
                            int lastUnderscoreIndex = procedureName.IndexOf("_", moduleName.Length + 2);

                            string tableName   = procedureName.Substring(moduleName.Length + 1, lastUnderscoreIndex - moduleName.Length - 1);
                            string catalogName = (string)procRow["ROUTINE_CATALOG"];

                            if (catalogName != "def")
                            {
                                throw new ApplicationException("Unexpected catalog name found: " + catalogName);
                            }


                            if (tableDefMap.ContainsKey(tableName) == false)
                            {
                                throw new ApplicationException("Table " + tableName + " referenced in stored procedure " + procedureName + " was not found in table definitions.");
                            }
                            TableDef tableDef = tableDefMap[tableName];

                            ProcedureDef procedureDef = new ProcedureDef {
                                ProcedureName   = procedureName,
                                TableDef        = tableDef,
                                ParameterDefMap = new Dictionary <string, ParameterDef>(),
                                FieldDefMap     = new Dictionary <string, FieldDef>()

                                                  /* ReadOnly, OutputsRows */
                            };

                            /* TODO: there may be some issues here if we require list and read functions to a data access level of reads sql data, i think
                             * it may change the transaction scope if you mix with modifies sql data (not sure) */
                            switch ((string)procRow["SQL_DATA_ACCESS"])
                            {
                            case "READS SQL DATA":
                                procedureDef.ReadOnly    = true;
                                procedureDef.OutputsRows = true;
                                break;

                            case "MODIFIES SQL DATA":
                                procedureDef.ReadOnly    = false;
                                procedureDef.OutputsRows = false;
                                break;

                            default:
                                throw new ApplicationException("Unrecognized SQL Data Access setting for procedure " + procedureName + ": " + procRow["SQL_DATA_ACCESS"]);
                            }


                            tableDef.ProcedureDefMap[procedureName] = procedureDef;
                            globalProcedureDefMap[procedureName]    = procedureDef;
                        }
                    }
                }
            }



            PopulateParameters(databaseName, moduleName, globalProcedureDefMap);


            /*
             * call each procedure to see the result set
             *
             */



            foreach (ProcedureDef procedureDef in globalProcedureDefMap.Values)
            {
                if (procedureDef.OutputsRows)
                {
                    MySqlTransaction trans = this.mySqlConnection.BeginTransaction();

                    using (MySqlCommand command = new MySqlCommand()
                    {
                        CommandText = procedureDef.ProcedureName,
                        CommandType = CommandType.StoredProcedure,
                        Connection = this.mySqlConnection
                    }) {
                        foreach (ParameterDef parameterDef in procedureDef.ParameterDefMap.Values)
                        {
                            ParameterDirection direction;
                            if (parameterDef.IsOutParameter)
                            {
                                direction = ParameterDirection.Output;
                            }
                            else
                            {
                                direction = ParameterDirection.Input;
                            }

                            var parameter = new MySqlParameter {
                                ParameterName = parameterDef.ParameterName,
                                Direction     = direction,
                                Size          = parameterDef.ParameterSize,
                                MySqlDbType   = GetMySqlDbType(parameterDef.ParameterDataTypeCode)
                            };


                            /*              for (Parameter p : proc.parameters) {
                             * p.sqlType.setTestValue(cs, p.procParamName);
                             * }
                             */
                            parameter.Value = DBNull.Value;

                            command.Parameters.Add(parameter);
                        }



                        /* alternatively for MSSQL at least:
                         *
                         * SELECT COLUMN_NAME
                         * FROM
                         * INFORMATION_SCHEMA.COLUMNS
                         * WHERE
                         * TABLE_NAME = 'vwGetData'
                         * ORDER BY
                         * ORDINAL_POSITION ASC;
                         *
                         */
                        // cs.setMaxRows(0);


                        DataTable tableSchema;

                        Dictionary <string, string> fieldTypeLookup = new Dictionary <string, string>();

                        using (var reader = command.ExecuteReader(CommandBehavior.SchemaOnly)) {
                            reader.Read();
                            tableSchema = reader.GetSchemaTable();
                            for (int i = 0; i < reader.FieldCount; i++)
                            {
                                fieldTypeLookup[reader.GetName(i)] = reader.GetDataTypeName(i);
                            }
                        }
                        trans.Rollback();


                        foreach (DataRow row in tableSchema.Rows)
                        {
                            /* IsIdentity */

                            /*
                             * int columnSize = (int)row["ColumnSize"];
                             * string sqlTypeCode =
                             *      bool isReadOnly = (bool)row["IsReadOnly"];
                             * bool isPrimaryKey = (bool)row["IsKey"];
                             * bool isAutoIncrement = (bool)row["IsAutoIncrement"];
                             */

                            string fieldName      = row["ColumnName"].ToString();
                            string baseTableName  = row["BaseTableName"].ToString();
                            string baseColumnName = row["BaseColumnName"].ToString();

                            bool isNullable = (bool)row["AllowDBNull"];

                            string dataTypeCode = TypeConvertor.ConvertSQLToCSharp(fieldTypeLookup[fieldName].ToLowerInvariant());

                            /* TODO: This check wouldn't really be necessary if we could rely on GetSchemaTable's DataType field */
                            if (tableDefMap.ContainsKey(baseTableName))
                            {
                                if (tableDefMap[baseTableName].ColumnDefMap.ContainsKey(baseColumnName))
                                {
                                    string newDataTypeCode = tableDefMap[baseTableName].ColumnDefMap[baseColumnName].ColumnType;
                                    if (newDataTypeCode != dataTypeCode)
                                    {
                                        Shared.Warning(" GetTableSchema reported an incorrect data type of " + dataTypeCode + " from stored procedure " + procedureDef.ProcedureName + ", field " + fieldName + ", instead of the source table's column data type of " + newDataTypeCode + ".");
                                        dataTypeCode = newDataTypeCode;
                                    }
                                }
                            }

                            FieldDef fieldDef = new FieldDef {
                                FieldName      = fieldName,
                                ProcedureDef   = procedureDef,
                                DataTypeCode   = dataTypeCode,
                                IsNullable     = isNullable,
                                BaseTableName  = baseTableName,
                                BaseColumnName = baseColumnName
                            };


                            procedureDef.FieldDefMap[fieldDef.FieldName] = fieldDef;
                        }
                    }
                }
            }

            return(globalProcedureDefMap.Values.ToList <ProcedureDef>());
        }
Exemplo n.º 6
0
        public static List <ModelDef> CreateModelDefList(string modelNamespace,
                                                         string moduleName,
                                                         Dictionary <string, ModelDef> modelDefMap,
                                                         List <ProcedureDef> procedureDefList,
                                                         List <string> ignoreTableNameList,
                                                         List <TableMapping> tableMappingList,
                                                         bool cleanOracle)
        {
            //		List<ModelDef> modelDefList = new List<ModelDef>();

            foreach (ProcedureDef procedureDef in procedureDefList)
            {
                string procedureName = procedureDef.ProcedureName;

                int firstUnderscoreIndex  = procedureName.IndexOf('_');
                int secondUnderscoreIndex = procedureName.IndexOf('_', firstUnderscoreIndex + 1);
                // int lastUnderscoreIndex = procedureName.LastIndexOf('_');

                // string modelName = procedureName.Substring(firstUnderscoreIndex + 1, lastUnderscoreIndex - firstUnderscoreIndex - 1);
                // string functionName = procedureName.Substring(lastUnderscoreIndex + 1);
                /* This assumes that no tables have underscores in their names */
                /* TODO: probably need an table name underscore removal method elsewhere. */
                string modelName    = procedureName.Substring(firstUnderscoreIndex + 1, secondUnderscoreIndex - firstUnderscoreIndex - 1);
                string functionName = procedureName.Substring(secondUnderscoreIndex + 1);

                /* skip tables we are ignoring */
                if (ignoreTableNameList.Contains(modelName))
                {
                    continue;
                }

                ModelDef modelDef = null;
                if (modelDefMap.ContainsKey(modelName))
                {
                    modelDef = modelDefMap[modelName];
                }
                else
                {
                    Shared.Info("Adding a virtual model after table named " + modelName + " from procedure " + procedureName + " which did not have a matching model in the models collection.");
                    modelDef = new ModelDef {
                        ModelName              = modelName,
                        FieldDefMap            = new Dictionary <string, FieldDef>(),
                        FunctionDefList        = new List <FunctionDef>(),
                        Namespace              = "",
                        PropertyDefMap         = new Dictionary <string, PropertyDef>(),
                        UsesBuildListFunction  = false,
                        UsesMakeObjectFunction = false,
                        IsJustTable            = true
                    };
                    modelDefMap[modelName] = modelDef;
                }

                FunctionDef functionDef = new FunctionDef {
                    FunctionName    = functionName,
                    ProcedureDef    = procedureDef,
                    ArgumentDefList = new List <ArgumentDef>()
                };

                modelDef.FunctionDefList.Add(functionDef);

                bool isSingleRow = (functionName.StartsWith("Read"));

                if (procedureDef.OutputsRows == true)
                {
                    functionDef.OutputsList         = true;
                    modelDef.UsesMakeObjectFunction = true;
                    functionDef.ReturnTypeCode      = modelDef.ModelName;
                    functionDef.ReturnTypeNamespace = modelDef.Namespace;
                    if (isSingleRow == true)
                    {
                        functionDef.OutputsList   = false;
                        functionDef.OutputsObject = true;
                    }
                    else
                    {
                        functionDef.OutputsList        = true;
                        functionDef.OutputsObject      = false;
                        modelDef.UsesBuildListFunction = true;
                    }
                }
                else
                {
                    functionDef.OutputsList   = false;
                    functionDef.OutputsObject = false;
                }

                foreach (ParameterDef parameterDef in procedureDef.ParameterDefMap.Values)
                {
                    string typeCode = TypeConvertor.ConvertNullableSQLToCSharp(parameterDef.ParameterDataTypeCode, parameterDef.IsNullable);

                    if (parameterDef.IsOutParameter == true)
                    {
                        if (functionDef.ReturnTypeCode != null)
                        {
                            throw new ApplicationException("Stored procedure " + procedureDef.ProcedureName + " returns row data but also has an out parameter: " + parameterDef.ParameterName);
                        }
                        functionDef.ReturnTypeCode      = typeCode;
                        functionDef.ReturnTypeNamespace = null;
                    }
                    else
                    {
                        bool isNullable = false;
                        if (typeCode != "string")
                        {
                            if (parameterDef.ColumnDef != null)
                            {
                                if (parameterDef.ColumnDef.IsNullable == true)
                                {
                                    isNullable = true;
                                }
                            }
                            else
                            {
                                /* if we don't know, we are going to allow them */
                                isNullable = true;
                            }
                        }



                        ArgumentDef argumentDef = new ArgumentDef {
                            ArgumentName     = Char.ToLowerInvariant(parameterDef.ParameterName[1]) + parameterDef.ParameterName.Substring(2),
                            ArgumentTypeCode = typeCode,
                            ParameterDef     = parameterDef,
                            IsNullable       = isNullable
                        };

                        parameterDef.ArgumentDef = argumentDef;

                        string      parameterName = parameterDef.ParameterName;
                        PropertyDef propertyDef   = modelDef.GetLikelyPropertyDef(parameterDef.ParameterName.Substring(1));

                        if (propertyDef != null)
                        {
                            argumentDef.PropertyDef  = propertyDef;
                            parameterDef.PropertyDef = propertyDef;
                            // Shared.Info($"DEBUG: Found propertyDef of {propertyDef.PropertyName} for parameterName:{parameterDef.ParameterName} in function {functionName}.");

                            /* TODO: seems like there should be a better way of storing isNullable at the property level */
                            /* we can't know from the models property type if strings are nullable or not so we just always assume they are */
                            if (propertyDef.PropertyTypeCode.EndsWith("?") == true || propertyDef.PropertyTypeCode == "string")
                            {
                                argumentDef.IsNullable  = true;
                                parameterDef.IsNullable = true;
                            }
                        }
                        else
                        {
                            Shared.Info($"Warning:  Could not find a propertyDef for parameterName:{parameterDef.ParameterName} in function {functionName} of {modelName}..");
                        }

                        functionDef.ArgumentDefList.Add(argumentDef);
                    }
                }

                if (procedureDef.OutputsRows == true)
                {
                    functionDef.OutputPropertyDefList = new List <PropertyDef>();
                    foreach (FieldDef fieldDef in procedureDef.FieldDefMap.Values)
                    {
                        string fieldName = fieldDef.FieldName;

                        string convertedFieldName = NameMapping.MakeCleanColumnName(tableMappingList, fieldDef.BaseTableName, modelDef.ModelName, fieldName, cleanOracle);

                        PropertyDef propertyDef = modelDef.GetLikelyPropertyDef(convertedFieldName);

                        /* We can easily get a field that is several layers back from our root object from joins
                         * in the query.
                         * for example Book.Author.City.State.Country.CountryName, and the query returns CountryName.
                         * We need to work down through the object graph to find the model that matches the table
                         * which that field is using.
                         * It may be that in the initial procedure read when we query the first recordset, with a browse value that
                         * returns join columns, that we can use that information to traverse the model tree more
                         * directly.
                         */
                        List <PropertyDef> propertyDefChain = null;
                        if (propertyDef == null)
                        {
                            var referencedModelName = NameMapping.MakeCleanTableName(tableMappingList, fieldDef.BaseTableName, cleanOracle);

                            // Shared.Info($"DEBUG:convertedFieldName:{convertedFieldName}, fieldDef.BaseTableName={fieldDef.BaseTableName}, referencedModelName={referencedModelName}");
                            if (modelDefMap.ContainsKey(referencedModelName) == true)
                            {
                                var referencedModelDef = modelDefMap[referencedModelName];

                                var usedModelDefList = new List <ModelDef>()
                                {
                                    modelDef
                                };
                                propertyDefChain = modelDef.ScanForLikelyPropertyDef(new List <PropertyDef>(), convertedFieldName, referencedModelDef, modelDefMap.Values.ToList <ModelDef>(), usedModelDefList);
                                if (propertyDefChain != null)
                                {
                                    //Shared.Info($"DEBUG: Found propertydef chain! fieldName:{convertedFieldName} in procedure {procedureDef.ProcedureName}");
                                    //propertyDefChain.ForEach(x => {
                                    //	Shared.Info($"{x.PropertyTypeNamespace}.{x.PropertyTypeCode} {x.PropertyName}");
                                    //});
                                }
                            }
                        }

                        /* if we didn't find a propertydef nor a propertydefchain, then it belongs as part of a function-specific Result output */
                        if (propertyDef == null && propertyDefChain == null)
                        {
                            if (functionDef.UsesResult == false)
                            {
                                functionDef.UsesResult            = true;
                                functionDef.ResultPropertyDefList = new List <ResultPropertyDef>();
                            }
                            functionDef.ResultPropertyDefList.Add(new ResultPropertyDef {
                                PropertyName     = CleanPropertyName(convertedFieldName),
                                PropertyTypeCode = fieldDef.DataTypeCode,
                                FieldDef         = fieldDef
                            });
                            Shared.Info($"Warning:  Could not find a propertyDef for fieldName \"{convertedFieldName}\" in procedure \"{procedureDef.ProcedureName}\".  " +
                                        $"The base table name for this field at the SQL level was \"{fieldDef.BaseTableName}\".  " +
                                        $"The converted model name was computed as \"{NameMapping.MakeCleanTableName(tableMappingList, fieldDef.BaseTableName, cleanOracle)}\".  " +
                                        $"This field will be included as a property in a result class labeled \"{functionDef.FunctionName}Result\" created just for the output of this function.");
                        }



                        /* TODO: Commented the type check because it couldn't resolve object v. key value.  May not be necessary really.
                         * /*
                         *
                         *                                      string propertyTypeCode = TypeConvertor.ConvertNullableSQLToCSharp(fieldDef.DataTypeCode, fieldDef.IsNullable);
                         *
                         *                                      if (propertyDef.PropertyTypeCode != propertyTypeCode) {
                         *                                              throw new ApplicationException("PropertyTypeCode for " + modelDef.ModelName + "." + propertyDef.PropertyName + " found " + propertyDef.PropertyTypeCode + " but wanted " + propertyTypeCode + " based on field " + fieldDef.FieldName + " with data type " +  fieldDef.DataTypeCode + " and IsNullable=" + fieldDef.IsNullable);
                         *                                      }
                         */


                        // propertyDef.FieldDefList.Add(fieldDef);
                        fieldDef.PropertyDef      = propertyDef;
                        fieldDef.PropertyDefChain = propertyDefChain;
                        functionDef.OutputPropertyDefList.Add(propertyDef);

                        if (modelDef.FieldDefMap.ContainsKey(fieldDef.FieldName))
                        {
                            FieldDef foundFieldDef = modelDef.FieldDefMap[fieldDef.FieldName];
                            if (foundFieldDef.BaseTableName != fieldDef.BaseTableName)
                            {
                                throw new ApplicationException("A stored procedure (" + procedureDef.ProcedureName + ") based on model " + modelDef.ModelName + " returned a field pointing to a base table named " + fieldDef.BaseTableName + ", but another procedure (" + foundFieldDef.ProcedureDef.ProcedureName + " had produced a field with the same name based on table " + foundFieldDef.BaseTableName + ".  Consider using two different names for this value in the two procedures.");
                            }
                        }
                        else
                        {
                            modelDef.FieldDefMap[fieldDef.FieldName] = fieldDef;
                        }
                    }
                }
            }

            return(modelDefMap.Values.ToList <ModelDef>());
        }
Exemplo n.º 7
0
        public static void MakeModels(List <TableDef> tableDefList, string namespaceText, string directory, List <TableMapping> tableMappingList, bool cleanOracle)
        {
            if (directory.EndsWith(Path.DirectorySeparatorChar.ToString(), false, CultureInfo.InvariantCulture) == false)
            {
                directory += Path.DirectorySeparatorChar;
            }
            foreach (var tableDef in tableDefList.OrderBy(x => x.TableName))
            {
                /* TODO: For now we skip views, but should we? */
                if (tableDef.TableType == "TABLE")
                {
                    Shared.Info("Making model from table " + tableDef.TableName);

                    var modelName = NameMapping.MakeCleanTableName(tableMappingList, tableDef.TableName, cleanOracle);
                    Shared.Info($"\t\tusing model name {modelName}");

                    StringBuilder buildText = new StringBuilder();

                    buildText.AppendLine("namespace " + namespaceText + " {\n");
                    buildText.AppendLine("\tpublic partial class " + modelName + " {\n");
                    buildText.AppendLine();

                    bool needsSystem = false;

                    foreach (var columnDef in tableDef.ColumnDefMap.Values)
                    {
                        string columnTypeCode;
                        string columnName = columnDef.ColumnName;

                        string convertedColumnName = NameMapping.MakeCleanColumnName(tableMappingList, tableDef.TableName, modelName, columnName, cleanOracle);


                        if (columnDef.ReferencedTableDef != null)
                        {
                            if (convertedColumnName.EndsWith("Key", StringComparison.InvariantCultureIgnoreCase))
                            {
                                convertedColumnName = convertedColumnName.Substring(0, convertedColumnName.Length - 3);
                            }
                            var rawReferencedTableName = columnDef.ReferencedTableDef.TableName;
                            columnTypeCode = NameMapping.MakeCleanTableName(tableMappingList, rawReferencedTableName, cleanOracle);
                        }
                        else
                        {
                            columnTypeCode = TypeConvertor.ConvertSQLToCSharp(columnDef.ColumnType);
                            if (columnTypeCode == "DateTime")
                            {
                                needsSystem = true;
                            }
                            if (columnTypeCode.Contains("[]"))
                            {
                                needsSystem = true;
                            }
                            else
                            {
                                if (columnDef.ForceToBit == true)
                                {
                                    columnTypeCode = "bool";
                                }
                                if (columnDef.IsNullable && columnTypeCode != "string")
                                {
                                    columnTypeCode += "?";
                                }
                            }
                        }



                        buildText.AppendLine("\t\tpublic " + columnTypeCode + " " + convertedColumnName + " { get; set; }");
                    }

                    buildText.AppendLine("\t}");
                    buildText.Append("}");

                    if (needsSystem)
                    {
                        buildText.Insert(0, "using System;" + Environment.NewLine);
                    }

                    File.WriteAllText(directory + modelName + ".cs", buildText.ToString());
                }
            }

            /* TODO: consider whether we want to make collections when our tables are referenced */
        }