Пример #1
0
 public void AddMakeObjectCallFunctionArguments(StringBuilder buildText,
                                                Dictionary <string, string> namespaceTagMap,
                                                ModelDef baseModelDef,
                                                List <ModelDef> modelDefList)
 {
     if (baseModelDef.IsAbstract)
     {
         buildText.AppendLine(",");
         buildText.Append($"createNew{baseModelDef.ModelName}ObjectFunction");
     }
     baseModelDef.FieldDefMap.Values
     .Where(x => x.PropertyDef != null)
     .Select(x => {
         var def = x.PropertyDef.GetModelDef(modelDefList);
         return(def);
     })
     .Where(x => x != null && x.IsAbstract == true && x != baseModelDef)
     .Distinct()
     .OrderBy(x => x.ModelName)
     .ToList()
     .ForEach(x => {
         buildText.AppendLine(",");
         buildText.Append($"createNew{x.ModelName}ObjectFunction");
     });
 }
Пример #2
0
        public string GetNewObjectFunctionArguments(Dictionary <string, string> namespaceTagMap,
                                                    ModelDef baseModelDef,
                                                    List <ModelDef> modelDefList)
        {
            var buildText = new StringBuilder();

            if (baseModelDef.IsAbstract)
            {
                buildText.AppendLine(",");
                buildText.Append($"\t\t\t\t\t\tFunc<{namespaceTagMap[baseModelDef.Namespace]}.{baseModelDef.ModelName}> createNew{baseModelDef.ModelName}ObjectFunction");
            }
            baseModelDef.FieldDefMap.Values
            .Where(x => x.PropertyDef != null)
            .Select(x => new { ModelDef    = x.PropertyDef.GetModelDef(modelDefList),
                               IsInterface = x.PropertyDef.IsInterface })
            .Where(x => x.ModelDef != null && x.ModelDef.IsAbstract == true && x.ModelDef != baseModelDef)
            .Distinct()
            .OrderBy(x => x.ModelDef.ModelName)
            .ToList()
            .ForEach(x => {
                buildText.AppendLine(",");
                buildText.Append($"\t\t\t\t\t\tFunc<{namespaceTagMap[x.ModelDef.Namespace]}.");
                if (x.IsInterface)
                {
                    buildText.Append("I");
                }
                buildText.Append($"{x.ModelDef.ModelName}> createNew{x.ModelDef.ModelName}ObjectFunction");
            });
            return(buildText.ToString());
        }
Пример #3
0
        public void CreateFunctionNoRows(StringBuilder buildText,
                                         StringBuilder internalInterfaceText,
                                         ModelDef modelDef,
                                         List <ModelDef> modelDefList,
                                         FunctionDef functionDef,
                                         Dictionary <string, string> namespaceTagMap)
        {
            /* version using all arguments */

            string functionString    = GetFunctionSignature(modelDef.ModelName, functionDef, namespaceTagMap);
            string argumentsString   = GetArguments(functionDef);
            string functionSignature = functionString + argumentsString + ")";

            internalInterfaceText.AppendLine("\t\t\t" + functionSignature + ";");
            internalInterfaceText.AppendLine();

            buildText.Append("\t\t\tpublic " + functionSignature + " {");
            AddUsingCommand(buildText, functionDef.ProcedureDef);

            AddCommandParameters(buildText, functionDef);

            buildText.AppendLine("");
            buildText.AppendLine("\t\t\t\t\tcommand.ExecuteNonQuery();");
            if (functionDef.ReturnTypeCode != null)
            {
                buildText.Append("\t\t\t\t\treturn (");
                if (functionDef.ReturnTypeNamespace != null)
                {
                    buildText.Append(namespaceTagMap[functionDef.ReturnTypeNamespace] + ".");
                }
                buildText.AppendLine(functionDef.ReturnTypeCode + ")outParameter.Value;");
            }
            buildText.AppendLine("\t\t\t\t}");
            buildText.AppendLine("\t\t\t}");
            buildText.AppendLine("");


            /* version using object as input */
            if (functionDef.ArgumentDefList.Any(x => x.PropertyDef != null))
            {
                string functionSignatureWithObject = functionString + GetObjectArgument(modelDef, namespaceTagMap)
                                                     + GetArgumentsNotInObject(functionDef) + ")";

                internalInterfaceText.AppendLine("\t\t\t" + functionSignatureWithObject + ";");
                internalInterfaceText.AppendLine();

                buildText.AppendLine("\t\t\tpublic " + functionSignatureWithObject + " {");
                buildText.Append("\t\t\t\t");
                // buildText.AppendLine($"var actionObject = new {modelDef.ModelName}();");
                buildText.Append("\t\t\t\t");
                if (functionDef.ReturnTypeCode != null)
                {
                    buildText.Append("return ");
                }
                buildText.AppendLine("this." + functionDef.FunctionName + "(conn, trans,");
                AddFunctionArguments(buildText, modelDef, modelDefList, functionDef);

                buildText.AppendLine("\t\t\t}");
            }
        }
Пример #4
0
        /* returns new model defs added to map.  If an assembly B depends on another
         *      assembly A, then that assembly A should appear first in the list */
        public static List <ModelDef> AddToFromFile(Dictionary <string, ModelDef> modelDefMap, string fileName, string requiredNamespace)
        {
            List <ModelDef> newModelDefList = new List <ModelDef> ();

            /* load this assembly into our default context.  Additional dependent
             *      assemblies will then find the parent assemblies loaded. */
            var modelsAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(fileName);

            foreach (Type modelType in modelsAssembly.GetTypes())
            {
                bool wasCompilerGenerated =
                    Attribute.GetCustomAttribute(modelType, typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute)) != null;

                if (wasCompilerGenerated == false)
                {
                    ModelDef modelDef = new ModelDef {
                        ModelName       = modelType.Name,
                        Namespace       = modelType.Namespace,
                        FunctionDefList = new List <FunctionDef>(),
                        PropertyDefMap  = new Dictionary <string, PropertyDef>(),
                        FieldDefMap     = new Dictionary <string, FieldDef>(),
                        IsJustTable     = false,
                        IsAbstract      = modelType.IsAbstract
                    };

                    /* okay this is a little confusing because FieldDefMap we are using to store
                     * fields from the stored procedure results that match those in this class.  Fields
                     * in .NET's Reflection are all the class-level declarations that are not
                     * properties.  For our purposes we store them both like Properties.
                     */

                    foreach (FieldInfo info in modelType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        /* ignore private fields */
                        if ((info.Attributes & System.Reflection.FieldAttributes.Private) != System.Reflection.FieldAttributes.Private)
                        {
                            AddMember(modelDef, info.Name, info.FieldType, requiredNamespace);
                        }
                    }

                    foreach (PropertyInfo info in modelType.GetProperties())
                    {
                        AddMember(modelDef, info.Name, info.PropertyType, requiredNamespace);
                    }


                    /* if we have multiple models with the same name, only use the first one */
                    if (modelDefMap.ContainsKey(modelDef.ModelName) == false)
                    {
                        newModelDefList.Add(modelDef);
                        modelDefMap[modelDef.ModelName] = modelDef;
                    }

                    //				var typeInfo = info.GetTypeInfo();

                    //				Shared.Info(typeInfo.Name);
                }
            }
            return(newModelDefList);
        }
Пример #5
0
        public void CreateFunctionSingleRow(StringBuilder buildText,
                                            StringBuilder internalInterfaceText,
                                            ModelDef modelDef,
                                            List <ModelDef> modelDefList,
                                            FunctionDef functionDef,
                                            Dictionary <string, string> namespaceTagMap)
        {
            string functionString    = GetFunctionSignature(modelDef.ModelName, functionDef, namespaceTagMap);
            string newObjectString   = GetNewObjectFunctionArguments(namespaceTagMap, modelDef, modelDefList);
            string argumentsString   = GetArguments(functionDef);
            string functionSignature = functionString + newObjectString + argumentsString + ")";

            internalInterfaceText.AppendLine("\t\t\t" + functionSignature + ";");
            internalInterfaceText.AppendLine();

            buildText.AppendLine("\t\t\tpublic " + functionSignature + " {");
            AddUsingCommand(buildText, functionDef.ProcedureDef);
            AddCommandParameters(buildText, functionDef);
            buildText.AppendLine("\t\t\t\t\tusing (var reader = command.ExecuteReader()) {");
            buildText.AppendLine("\t\t\t\t\t\tif (reader.Read()) {");

            if (functionDef.UsesResult)
            {
                AddExtraResultFill(buildText, modelDef, modelDefList, functionDef, namespaceTagMap);
                buildText.AppendLine("\t\t\t\t\t\t\treturn item;");
            }
            else
            {
                buildText.Append("\t\t\t\t\t\t\treturn MakeObject(reader");
                AddMakeObjectCallFunctionArguments(buildText, namespaceTagMap, modelDef, modelDefList);
                buildText.AppendLine(", null);");
            }
            buildText.AppendLine("\t\t\t\t\t\t} else {");
            buildText.AppendLine("\t\t\t\t\t\t\treturn null;");
            buildText.AppendLine("\t\t\t\t\t\t}");
            buildText.AppendLine("\t\t\t\t\t}");
            buildText.AppendLine("\t\t\t\t}");
            buildText.AppendLine("\t\t\t}");
            buildText.AppendLine("");

            /* Only use the Object input version if there are fields that come from the object */
            if (functionDef.ArgumentDefList.Any(x => x.PropertyDef != null))
            {
                string functionSignatureWithObject = functionString + newObjectString + GetObjectArgument(modelDef, namespaceTagMap)
                                                     + GetArgumentsNotInObject(functionDef)
                                                     + ")";

                internalInterfaceText.AppendLine("\t\t\t" + functionSignatureWithObject + ";");
                internalInterfaceText.AppendLine();

                buildText.Append("\t\t\tpublic " + functionSignatureWithObject + " {");
                buildText.AppendLine("\t\t\t\treturn this." + functionDef.FunctionName + "(conn, trans");
                AddMakeObjectCallFunctionArguments(buildText, namespaceTagMap, modelDef, modelDefList);
                buildText.AppendLine(",");
                AddFunctionArguments(buildText, modelDef, modelDefList, functionDef);
                buildText.AppendLine("\t\t\t}");
            }
        }
Пример #6
0
        public string GetObjectArgument(ModelDef modelDef, Dictionary <string, string> namespaceTagMap)
        {
            StringBuilder buildText = new StringBuilder();

            buildText.AppendLine(",");
            buildText.Append("\t\t\t\t\t\t");
            buildText.AppendLine(namespaceTagMap[modelDef.Namespace] + "." + modelDef.ModelName + " inputObject");
            return(buildText.ToString());
        }
Пример #7
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;
        }
Пример #8
0
        // command.Parameters.Add(new SqlParameter("@OfficialPositionCode", officialPositionCode ?? DBNull.Value));


        public void AddBuildList(StringBuilder buildText,
                                 ModelDef modelDef,
                                 List <ModelDef> modelDefList,
                                 Dictionary <string, string> namespaceTagMap)
        {
            buildText.Append("\t\t\tprivate List<" + namespaceTagMap[modelDef.Namespace] + "." + modelDef.ModelName + "> BuildList(" + this.GetSqlCommandText() + " command");
            buildText.Append(GetNewObjectFunctionArguments(namespaceTagMap, modelDef, modelDefList));
            buildText.AppendLine(") {");
            buildText.AppendLine("\t\t\t\tvar list = new List<" + namespaceTagMap[modelDef.Namespace] + "." + modelDef.ModelName + ">();");
            buildText.AppendLine("\t\t\t\tusing (var reader = command.ExecuteReader()) {");
            buildText.AppendLine("\t\t\t\t\twhile (reader.Read()) {");
            buildText.Append("\t\t\t\t\t\tvar item = MakeObject(reader");
            AddMakeObjectCallFunctionArguments(buildText, namespaceTagMap, modelDef, modelDefList);
            buildText.AppendLine(", null);");
            buildText.AppendLine("\t\t\t\t\t\tlist.Add(item);");
            buildText.AppendLine("\t\t\t\t\t}");
            buildText.AppendLine("\t\t\t\t}");
            buildText.AppendLine("\t\t\t\treturn list;");
            buildText.AppendLine("\t\t\t}");
            buildText.AppendLine();
        }
Пример #9
0
        public void AddExtraResultFill(StringBuilder buildText, ModelDef modelDef, List <ModelDef> modelDefList, FunctionDef functionDef, Dictionary <string, string> namespaceTagMap)
        {
            buildText.AppendLine("\t\t\t\t\t\t\tvar item = new " + functionDef.FunctionName + "Result {");
            bool first = true;

            if (modelDef.IsJustTable == false)
            {
                buildText.Append("\t\t\t\t\t\t\t\t\t" + modelDef.ModelName + " = MakeObject(reader");
                AddMakeObjectCallFunctionArguments(buildText, namespaceTagMap, modelDef, modelDefList);

                buildText.Append(", null)");
                first = false;
            }
            foreach (var resultPropertyDef in functionDef.ResultPropertyDefList)
            {
                if (first == true)
                {
                    first = false;
                }
                else
                {
                    buildText.AppendLine(",");
                }


                var fieldDef = resultPropertyDef.FieldDef;

                buildText.Append("\t\t\t\t\t\t\t\t\t" + resultPropertyDef.PropertyName + " = ");
                if (fieldDef.IsNullable && resultPropertyDef.PropertyTypeCode != "string")
                {
                    OutputUnNull(buildText, resultPropertyDef.PropertyTypeCode, "reader[\"" + fieldDef.FieldName + "\"]");
                }
                else
                {
                    buildText.Append("(" + resultPropertyDef.PropertyTypeCode + ")reader[\"" + fieldDef.FieldName + "\"]");
                }
            }
            buildText.AppendLine("};");
        }
Пример #10
0
        public void CreateFunctionMultiRow(StringBuilder buildText,
                                           StringBuilder internalInterfaceText,
                                           ModelDef modelDef,
                                           List <ModelDef> modelDefList,
                                           FunctionDef functionDef,
                                           Dictionary <string, string> namespaceTagMap)
        {
            string functionString    = GetFunctionSignature(modelDef.ModelName, functionDef, namespaceTagMap);
            string newObjectString   = GetNewObjectFunctionArguments(namespaceTagMap, modelDef, modelDefList);
            string argumentsString   = GetArguments(functionDef);
            string functionSignature = functionString + newObjectString + argumentsString + ")";

            internalInterfaceText.AppendLine("\t\t\t" + functionSignature + ";");
            internalInterfaceText.AppendLine();

            buildText.AppendLine("\t\t\tpublic " + functionSignature + " {");
            AddUsingCommand(buildText, functionDef.ProcedureDef);
            AddCommandParameters(buildText, functionDef);

            if (functionDef.UsesResult == true)
            {
                buildText.AppendLine("\t\t\t\t\tvar list = new List<" + functionDef.FunctionName + "Result>();");
                buildText.AppendLine("\t\t\t\t\tusing (var reader = command.ExecuteReader()) {");
                buildText.AppendLine("\t\t\t\t\t\twhile (reader.Read()) {");
                AddExtraResultFill(buildText, modelDef, modelDefList, functionDef, namespaceTagMap);
                buildText.AppendLine("\t\t\t\t\t\t\tlist.Add(item);");
                buildText.AppendLine("\t\t\t\t\t\t}");
                buildText.AppendLine("\t\t\t\t\t}");
                buildText.AppendLine("\t\t\t\t\treturn list;");
            }
            else
            {
                buildText.Append("\t\t\t\t\treturn BuildList(command");
                AddMakeObjectCallFunctionArguments(buildText, namespaceTagMap, modelDef, modelDefList);
                buildText.AppendLine(");");
            }
            buildText.AppendLine("\t\t\t\t}");
            buildText.AppendLine("\t\t\t}");
        }
Пример #11
0
        public void AddMakeObject(StringBuilder buildText, ModelDef modelDef, List <ModelDef> modelDefList, Dictionary <string, string> namespaceTagMap)
        {
            var classText = namespaceTagMap[modelDef.Namespace] + "." + modelDef.ModelName;

            buildText.AppendLine($"\t\t\tprivate {classText} MakeObject(IDataRecord row");

            string newObjectString = GetNewObjectFunctionArguments(namespaceTagMap, modelDef, modelDefList);

            buildText.AppendLine(newObjectString);
            buildText.AppendLine(",");
            buildText.AppendLine($"\t\t\t\t\t\t{classText} targetToFill) {{");
            buildText.AppendLine("\t\t\t\t" + classText + " outputObject = null;");
            buildText.AppendLine("\t\t\t\tif (targetToFill != null) {");
            buildText.AppendLine("\t\t\t\t\toutputObject = targetToFill;");
            buildText.AppendLine("\t\t\t\t}");
            buildText.AppendLine("\t\t\t\telse {");
            buildText.Append("\t\t\t\t\toutputObject = ");
            if (modelDef.IsAbstract)
            {
                buildText.AppendLine($"createNew{modelDef.ModelName}ObjectFunction();");
            }
            else
            {
                buildText.AppendLine("new " + classText + "();");
            }
            buildText.AppendLine("\t\t\t\t}");
            buildText.AppendLine("");
            buildText.AppendLine("\t\t\t\tfor (var i = 0; i < row.FieldCount; i++) {");
            buildText.Append("\t\t\t\t\tFillField(outputObject, row.GetName(i), row.GetValue(i)");
            AddMakeObjectCallFunctionArguments(buildText, namespaceTagMap, modelDef, modelDefList);

            buildText.AppendLine(");");
            buildText.AppendLine("\t\t\t\t}");
            buildText.AppendLine("");
            buildText.AppendLine("\t\t\t\treturn outputObject;");
            buildText.AppendLine("\t\t\t}");
            buildText.AppendLine();

            buildText.Append("\t\t\tprivate void FillField(" + classText + " outputObject, string columnName, object value");
            buildText.Append(GetNewObjectFunctionArguments(namespaceTagMap, modelDef, modelDefList));
            buildText.AppendLine(") {");
            buildText.AppendLine("\t\t\t\tswitch (columnName) {");

            foreach (FieldDef fieldDef in modelDef.FieldDefMap.Values.OrderBy(x => x.FieldName))
            {
                PropertyDef propertyDef = fieldDef.PropertyDef;

                buildText.AppendLine("\t\t\t\t\tcase \"" + fieldDef.FieldName + "\":");

                var fieldTableName = fieldDef.ProcedureDef.TableDef.TableName;

                if (fieldDef.PropertyDefChain != null)
                {
                    /* TODO: Not exactly sure yet how to handle a NULL value for a secondary model's field */

                    var    bigName       = "outputObject";
                    string lastModelName = null;
                    foreach (PropertyDef subDef in fieldDef.PropertyDefChain)
                    {
                        if (subDef != fieldDef.PropertyDefChain.Last())
                        {
                            buildText.AppendLine($"\t\t\t\t\t\tif ({bigName}.{subDef.PropertyName} == null) {{");
                            buildText.AppendLine($"\t\t\t\t\t\t\t{bigName}.{subDef.PropertyName} = new {namespaceTagMap[subDef.PropertyTypeNamespace]}.{subDef.PropertyTypeCode}();");
                            buildText.AppendLine("\t\t\t\t\t\t}");
                            bigName      += "." + subDef.PropertyName;
                            lastModelName = subDef.PropertyTypeCode;
                        }
                        else
                        {
                            /* TODO: not sure this will work with schemas, have to try it */

                            /* TODO: don't use the DataAccess.<Model>.FillField function, because it will not exist unless
                             * we've referenced that model directly in a function.  Instead just populate the field immediately
                             * like we do any other field. */
                            // buildText.AppendLine("\t\t\t\t\t\tDataAccess." + lastModelName + ".FillField(" + bigName + ", \"" + fieldDef.FieldName + "\", value);");
                            buildText.Append($"\t\t\t\t\t\t{bigName}.{subDef.PropertyName} = ");
                            AddFillFieldColumnSet(buildText, fieldDef, subDef, namespaceTagMap);
                        }
                    }
                }
                else
                {
                    if (propertyDef != null && fieldDef.BaseTableName != "" && fieldDef.BaseTableName != fieldTableName)
                    {
                        /* TODO: I *think* we can remove this in favor of using a property def chain above */
                        /* e.g. Book table has a field for AuthorName, which would be in the Author table */
                        buildText.AppendLine("\t\t\t\t\t\tif (outputObject." + propertyDef.PropertyName + " == null) {");

                        //					Shared.Info($"DEBUG:fieldDef.FieldName={fieldDef.FieldName}, modelDef.ModelName={modelDef.ModelName}, propertyDef.PropertyName={propertyDef.PropertyName}, propertyDef.PropertyTypeNamespace={propertyDef.PropertyTypeNamespace}, fieldDef.BaseTableName={fieldDef.BaseTableName}");

                        buildText.AppendLine("\t\t\t\t\t\t\toutputObject." + propertyDef.PropertyName + " = new " + namespaceTagMap[propertyDef.PropertyTypeNamespace] + "." + fieldDef.BaseTableName + "();");
                        buildText.AppendLine("\t\t\t\t\t\t}");
                        buildText.AppendLine("\t\t\t\t\t\tDataAccess." + fieldDef.BaseTableName + ".FillField(outputObject." + propertyDef.PropertyName + ", \"" + fieldDef.FieldName + "\", value);");
                    }
                    else
                    {
                        if (propertyDef == null)
                        {
                            /* TODO: should this be empty, or should it maybe use a *Result class? */
                            buildText.AppendLine("\t\t\t\t\t\t/* ignoring field " + fieldDef.FieldName + " */");
                        }
                        else
                        {
                            if (propertyDef.IsReference == true)
                            {
                                buildText.AppendLine("\t\t\t\t\t\tif (value == DBNull.Value) {");
                                buildText.AppendLine("\t\t\t\t\t\t\toutputObject." + propertyDef.PropertyName + " = null;");
                                buildText.AppendLine("\t\t\t\t\t\t}");
                                buildText.AppendLine("\t\t\t\t\t\telse {");
                                buildText.AppendLine("\t\t\t\t\t\t\tif (outputObject." + propertyDef.PropertyName + " == null) {");

                                buildText.Append("\t\t\t\t\t\t\t\toutputObject." + propertyDef.PropertyName + " = ");
                                AddNewObjectFromPropertyDef(buildText, propertyDef, modelDefList, namespaceTagMap);

                                buildText.AppendLine("\t\t\t\t\t\t\t}");
                                buildText.AppendLine("\t\t\t\t\t\t\toutputObject." + propertyDef.PropertyName + "." + propertyDef.PropertyTypeCode + "ID = (" + fieldDef.DataTypeCode + ")value;");
                                buildText.AppendLine("\t\t\t\t\t\t}");
                            }
                            else
                            {
                                buildText.Append("\t\t\t\t\t\toutputObject." + propertyDef.PropertyName + " = ");
                                AddFillFieldColumnSet(buildText, fieldDef, propertyDef, namespaceTagMap);
                            }
                        }
                    }
                }
                buildText.AppendLine("\t\t\t\t\t\tbreak;");
            }
            buildText.AppendLine("\t\t\t\t\tdefault:");
            buildText.AppendLine("\t\t\t\t\t\tthrow new ApplicationException(\"Unrecognized column name: \" + columnName);");
            buildText.AppendLine("\t\t\t\t}");
            buildText.AppendLine("\t\t\t}");
        }
Пример #12
0
        public void AddFunctionArguments(StringBuilder buildText, ModelDef modelDef, List <ModelDef> modelDefList, FunctionDef functionDef)
        {
            bool firstParameter = true;

            foreach (ArgumentDef argumentDef in functionDef.ArgumentDefList)
            {
                if (firstParameter)
                {
                    firstParameter = false;
                }
                else
                {
                    buildText.AppendLine(",");
                }

                buildText.Append("\t\t\t\t\t\t");
                PropertyDef propertyDef = argumentDef.PropertyDef;

                if (propertyDef == null)
                {
                    /* display a friendly warning if the field might be missing in the target class */
                    if (argumentDef.ArgumentName.EndsWith("Key", false, CultureInfo.InvariantCulture))
                    {
                        Shared.Warning("Argument " + argumentDef.ArgumentName + " in function " + functionDef.FunctionName + " for " + functionDef.ProcedureDef.ProcedureName + " could not be found as a property of the model.  Perhaps a foreign key reference doesn't exist on that column of the database table?");
                    }
                    else
                    {
                        Shared.Warning("Argument " + argumentDef.ArgumentName + " in function " + functionDef.FunctionName + " for " + functionDef.ProcedureDef.ProcedureName + " could not be found as a property of the model.  This is normal when the stored procedure uses this field within the procedure as an external value that lives outside the table.  If not, please verify:" + Environment.NewLine + "\t\tShould the column exist in the model class but is missing?" + Environment.NewLine + "\t\tPerhaps it is spelled differently and needs an entry in the mapping file referenced by --namemapfile?");
                    }
                    buildText.Append(argumentDef.ArgumentName);
                }
                else
                {
                    if (propertyDef.IsReference)
                    {
                        string subPropertyName = propertyDef.PropertyName;
                        if (argumentDef.ArgumentName.EndsWith("Key", false, CultureInfo.InvariantCulture))
                        {
                            /* TODO: this is failing when type is an interface */

                            var referencedModelDef = propertyDef.GetModelDef(modelDefList);
                            var idPropertyName     = propertyDef.PropertyTypeCode + "ID";
                            var idPropertyDef      = referencedModelDef.PropertyDefMap[idPropertyName];
                            var idTypeCode         = idPropertyDef.PropertyTypeCode;

                            // buildText.Append($"/* {idPropertyName}, {idPropertyDef}, {idTypeCode}");
                            if (idTypeCode.EndsWith("?"))
                            {
                                subPropertyName = idPropertyName + ".Value";
                            }
                            else
                            {
                                subPropertyName = idPropertyName;
                            }
                        }
                        if (argumentDef.IsNullable)
                        {
                            // buildText.Append("(inputObject." + propertyDef.PropertyName + " == null) ? (" + argumentDef.ArgumentTypeCode + "?)null : inputObject." + propertyDef.PropertyName + "." + subPropertyName);
                            buildText.Append("inputObject." + propertyDef.PropertyName + "?." + subPropertyName);
                        }
                        else
                        {
                            buildText.Append("inputObject." + propertyDef.PropertyName + "." + subPropertyName);
                        }
                    }
                    else
                    {
                        buildText.Append("inputObject." + propertyDef.PropertyName);
                        if (propertyDef.IsEnum)
                        {
                            buildText.Append(".ToString()");
                        }
                    }
                }
            }
            buildText.AppendLine(");");
        }
Пример #13
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>());
        }
Пример #14
0
        public List <PropertyDef> ScanForLikelyPropertyDef(List <PropertyDef> incomingPropertyDefChain, string sqlName, ModelDef referencedModelDef, List <ModelDef> modelDefList, List <ModelDef> usedModelDefList)
        {
            /* used when we haven't found any property to use, but it might be that it is a property of a
             * referenced object (or of a reference to a reference etc.).  So drill down along the model map
             * to see if we can find one that matches.
             */

            foreach (var propertyDef in this.PropertyDefMap.Values)
            {
                if (propertyDef.PropertyTypeNamespace == "System.Collections.Generic")
                {
                    /* skip lists and dictionaries */
                }
                else if (propertyDef.IsReference)
                {
                    /* gets type model def with same namespace+modelname */
                    var subModelDef = modelDefList.FirstOrDefault(x => x.Namespace == propertyDef.PropertyTypeNamespace && x.ModelName == propertyDef.PropertyTypeCode);
                    if (subModelDef == null)
                    {
                        // Console.WriteLine("Warning: Property Def " + propertyDef.PropertyName + " had Model Def that was not found for Namespace==" + propertyDef.PropertyTypeNamespace + " and ModelName==" + propertyDef.PropertyTypeCode + ".  Skipping.");
                    }
                    else
                    {
                        if (usedModelDefList.Contains(subModelDef) == false)
                        {
                            usedModelDefList.Add(subModelDef);
                            var outputPropertyDefChain = new List <PropertyDef>(incomingPropertyDefChain);
                            outputPropertyDefChain.Add(propertyDef);
                            // Console.WriteLine($"DEBUG:sqlName:{sqlName},referencedModelDef.ModelName={referencedModelDef.ModelName}, subModelDef.ModelName={subModelDef.ModelName}");
                            if (subModelDef == referencedModelDef)
                            {
                                var newPropertyDef = subModelDef.GetLikelyPropertyDef(sqlName);
                                if (newPropertyDef != null)
                                {
                                    outputPropertyDefChain.Add(newPropertyDef);

                                    return(outputPropertyDefChain);
                                }
                            }
                            else
                            {
                                var bestResult = subModelDef.ScanForLikelyPropertyDef(outputPropertyDefChain, sqlName, referencedModelDef, modelDefList, usedModelDefList);
                                if (bestResult != null)
                                {
                                    return(bestResult);
                                }
                            }
                        }
                    }
                }
            }
            return(null);
        }