Esempio n. 1
0
        public SourceText GetInputTextForStoredProcedure(Definition.Schema schema, Definition.StoredProcedure storedProcedure)
        {
            var rootDir     = _output.GetOutputRootDir();
            var fileContent = File.ReadAllText(Path.Combine(rootDir.FullName, "DataContext", "Inputs", "Input.cs"));

            var tree = CSharpSyntaxTree.ParseText(fileContent);
            var root = tree.GetCompilationUnitRoot();

            // If Inputs contains a TableType, add using for TableTypes
            var schemesForTableTypes = storedProcedure.Input.Where(i => i.IsTableType ?? false)
                                       .GroupBy(t => (t.TableTypeSchemaName, t.TableTypeName), (key, group) => new
            {
                TableTypeSchemaName = key.TableTypeSchemaName,
                Result = group.First()
            }).Select(g => g.Result).ToList();

            var tableTypeSchemas = storedProcedure.Input.Where(i => i.IsTableType ?? false)
                                   .GroupBy(t => t.TableTypeSchemaName, (key, group) => key).ToList();

            foreach (var tableTypeSchema in tableTypeSchemas)
            {
                var tableTypeSchemaConfig = _configFile.Config.Schema.Find(s => s.Name.Equals(tableTypeSchema));
                // is schema of table type ignored and its an extension?
                var useFromLib = tableTypeSchemaConfig?.Status != SchemaStatusEnum.Build &&
                                 _configFile.Config.Project.Role.Kind == ERoleKind.Extension;

                var paramUsingDirective = useFromLib
                                    ? SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Role.LibNamespace}.TableTypes.{tableTypeSchema.FirstCharToUpper()}"))
                                    : _configFile.Config.Project.Role.Kind == ERoleKind.Lib
                                        ? SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Output.Namespace}.TableTypes.{tableTypeSchema.FirstCharToUpper()}"))
                                        : SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Output.Namespace}.DataContext.TableTypes.{tableTypeSchema.FirstCharToUpper()}"));
                root = root.AddUsings(paramUsingDirective);
            }

            // Replace Namespace
            if (_configFile.Config.Project.Role.Kind == ERoleKind.Lib)
            {
                root = root.ReplaceNamespace(ns => ns.Replace("Source.DataContext", _configFile.Config.Project.Output.Namespace).Replace("Schema", schema.Name));
            }
            else
            {
                root = root.ReplaceNamespace(ns => ns.Replace("Source", _configFile.Config.Project.Output.Namespace).Replace("Schema", schema.Name));
            }

            // Replace ClassName
            root = root.ReplaceClassName(ci => ci.Replace("Input", $"{storedProcedure.Name}Input"));
            var nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
            var classNode = (ClassDeclarationSyntax)nsNode.Members[0];


            // Create obsolete constructor
            var obsoleteContructor = classNode.CreateConstructor($"{storedProcedure.Name}Input");

            root      = root.AddObsoleteAttribute(ref obsoleteContructor, "This empty contructor will be removed in vNext. Please use constructor with parameters.");
            root      = root.AddConstructor(ref classNode, obsoleteContructor);
            nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
            classNode = (ClassDeclarationSyntax)nsNode.Members[0];

            var inputs = storedProcedure.Input.Where(i => !i.IsOutput).ToList();
            // Constructor with params
            var constructor = classNode.CreateConstructor($"{storedProcedure.Name}Input");
            var parameters  = inputs.Select(input =>
            {
                return(SyntaxFactory.Parameter(SyntaxFactory.Identifier(GetIdentifierFromSqlInputTableType(input.Name)))
                       .WithType(
                           input.IsTableType ?? false
                        ? GetTypeSyntaxForTableType(input)
                        : ParseTypeFromSqlDbTypeName(input.SqlTypeName, input.IsNullable ?? false)
                           ));
            }).ToArray();

            var constructorParams = constructor.ParameterList.AddParameters(parameters);

            constructor = constructor.WithParameterList(constructorParams);

            foreach (var input in inputs)
            {
                var constructorStatement = ExpressionHelper.AssignmentStatement(TokenHelper.Parse(input.Name).ToString(), GetIdentifierFromSqlInputTableType(input.Name));
                var newStatements        = constructor.Body.Statements.Add(constructorStatement);
                constructor = constructor.WithBody(constructor.Body.WithStatements(newStatements));
            }

            root      = root.AddConstructor(ref classNode, constructor);
            nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
            classNode = (ClassDeclarationSyntax)nsNode.Members[0];

            // Generate Properies
            // https://stackoverflow.com/questions/45160694/adding-new-field-declaration-to-class-with-roslyn

            foreach (var item in storedProcedure.Input)
            {
                nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
                classNode = (ClassDeclarationSyntax)nsNode.Members[0];

                var isTableType  = item.IsTableType ?? false;
                var propertyType = isTableType
                    ? GetTypeSyntaxForTableType(item)
                    : ParseTypeFromSqlDbTypeName(item.SqlTypeName, item.IsNullable ?? false);

                var propertyNode = classNode.CreateProperty(propertyType, item.Name);

                if (!isTableType)
                {
                    // Add Attribute for NVARCHAR with MaxLength
                    if ((item.SqlTypeName?.Equals(SqlDbType.NVarChar.ToString(), StringComparison.InvariantCultureIgnoreCase) ?? false) &&
                        item.MaxLength.HasValue)
                    {
                        var attributes = propertyNode.AttributeLists.Add(
                            SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(
                                                            SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("MaxLength"), SyntaxFactory.ParseAttributeArgumentList($"({item.MaxLength})"))
                                                            )).NormalizeWhitespace());

                        propertyNode = propertyNode.WithAttributeLists(attributes);
                    }
                }

                root = root.AddProperty(ref classNode, propertyNode);
            }

            return(root.NormalizeWhitespace().GetText());
        }