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

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

            // 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("Output", storedProcedure.GetOutputTypeName()));

            // Generate Properies
            // https://stackoverflow.com/questions/45160694/adding-new-field-declaration-to-class-with-roslyn
            var nsNode       = (NamespaceDeclarationSyntax)root.Members[0];
            var classNode    = (ClassDeclarationSyntax)nsNode.Members[0];
            var propertyNode = (PropertyDeclarationSyntax)classNode.Members[0];
            var outputs      = storedProcedure.Input?.Where(i => i.IsOutput).ToList() ?? new List <StoredProcedureInputModel>();

            foreach (var output in outputs)
            {
                nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
                classNode = (ClassDeclarationSyntax)nsNode.Members[0];

                var propertyIdentifier = TokenHelper.Parse(output.Name);
                propertyNode = propertyNode
                               .WithType(ParseTypeFromSqlDbTypeName(output.SqlTypeName, output.IsNullable ?? false));

                propertyNode = propertyNode
                               .WithIdentifier(propertyIdentifier);

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

            // Remove template Property
            nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
            classNode = (ClassDeclarationSyntax)nsNode.Members[0];
            root      = root.ReplaceNode(classNode, classNode.WithMembers(new SyntaxList <MemberDeclarationSyntax>(classNode.Members.Cast <PropertyDeclarationSyntax>().Skip(1))));

            return(root.NormalizeWhitespace().GetText());
        }
Esempio n. 2
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());
        }
Esempio n. 3
0
        public SourceText GetStoredProcedureText(Definition.Schema schema, List <Definition.StoredProcedure> storedProcedures)
        {
            var entityName = storedProcedures.First().EntityName;

            var rootDir     = _output.GetOutputRootDir();
            var fileContent = File.ReadAllText(Path.Combine(rootDir.FullName, "DataContext", "StoredProcedures", "StoredProcedureExtensions.cs"));

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

            // If its an extension, add usings for the lib
            if (_configFile.Config.Project.Role.Kind == ERoleKind.Extension)
            {
                var libUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Role.LibNamespace}"));
                root = root.AddUsings(libUsingDirective).NormalizeWhitespace();

                var libModelUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Role.LibNamespace}.Models"));
                root = root.AddUsings(libModelUsingDirective).NormalizeWhitespace();

                var libOutputsUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Role.LibNamespace}.Outputs"));
                root = root.AddUsings(libOutputsUsingDirective).NormalizeWhitespace();
            }
            else
            {
                // For libs and default projects
                // Add Using for common Models (e.g. CrudResult)
                if (storedProcedures.Any(i => i.ReadWriteKind == Definition.ReadWriteKindEnum.Write))
                {
                    for (var i = 0; i < root.Usings.Count; i++)
                    {
                        var usingDirective = root.Usings[i];
                        var newUsingName   = _configFile.Config.Project.Role.Kind == ERoleKind.Lib
                            ? SyntaxFactory.ParseName($"{usingDirective.Name.ToString().Replace("Source.DataContext", _configFile.Config.Project.Output.Namespace)}")
                            : SyntaxFactory.ParseName($"{usingDirective.Name.ToString().Replace("Source", _configFile.Config.Project.Output.Namespace)}");
                        root = root.ReplaceNode(usingDirective, usingDirective.WithName(newUsingName));
                    }
                }
            }

            // Add Using for Models
            // TODO: i.Output?.Count() -> Implement a Property "IsScalar" and "IsJson"
            if (storedProcedures.Any(i => i.ReadWriteKind == Definition.ReadWriteKindEnum.Read && i.Output?.Count() > 1))
            {
                var modelUsingDirective = _configFile.Config.Project.Role.Kind == ERoleKind.Lib
                    ? SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Output.Namespace}.Models.{schema.Name}"))
                    : SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Output.Namespace}.DataContext.Models.{schema.Name}"));
                root = root.AddUsings(modelUsingDirective).NormalizeWhitespace();
            }

            // Add Usings for Inputs
            if (storedProcedures.Any(s => s.HasInputs()))
            {
                var inputUsingDirective = _configFile.Config.Project.Role.Kind == ERoleKind.Lib
                    ? SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Output.Namespace}.Inputs.{schema.Name}"))
                    : SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Output.Namespace}.DataContext.Inputs.{schema.Name}"));
                root = root.AddUsings(inputUsingDirective.NormalizeWhitespace().WithLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed)).WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);
            }

            // Add Usings for Outputs
            if (storedProcedures.Any(s => s.HasOutputs() && !s.IsDefaultOutput()))
            {
                var inputUsingDirective = _configFile.Config.Project.Role.Kind == ERoleKind.Lib
                    ? SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Output.Namespace}.Outputs.{schema.Name}"))
                    : SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Output.Namespace}.DataContext.Outputs.{schema.Name}"));
                root = root.AddUsings(inputUsingDirective.NormalizeWhitespace().WithLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed)).WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);
            }

            // Add Usings for TableTypes
            // If Inputs contains a TableType, add using for TableTypes
            var tableTypeSchemas = storedProcedures.SelectMany(sp => sp.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));
                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.NormalizeWhitespace().WithLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed)).WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);
            }

            // Remove Template Usings
            var usings = root.Usings.Where(_ => !_.Name.ToString().StartsWith("Source."));

            root = root.WithUsings(new SyntaxList <UsingDirectiveSyntax>(usings));

            // 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("StoredProcedure", entityName));

            var nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
            var classNode = (ClassDeclarationSyntax)nsNode.Members[0];

            // Generate Methods
            foreach (var storedProcedure in storedProcedures)
            {
                nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
                classNode = (ClassDeclarationSyntax)nsNode.Members[0];

                // Extension for IAppDbContextPipe
                var originMethodNode = (MethodDeclarationSyntax)classNode.Members[0];
                originMethodNode = GenerateStoredProcedureMethodText(originMethodNode, storedProcedure);
                root             = root.AddMethod(ref classNode, originMethodNode);

                nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
                classNode = (ClassDeclarationSyntax)nsNode.Members[0];

                // Overloaded extension with IAppDbContext
                var overloadOptionsMethodNode = (MethodDeclarationSyntax)classNode.Members[1];
                overloadOptionsMethodNode = GenerateStoredProcedureMethodText(overloadOptionsMethodNode, storedProcedure, true);
                root = root.AddMethod(ref classNode, overloadOptionsMethodNode);
            }

            // Remove template Method
            nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
            classNode = (ClassDeclarationSyntax)nsNode.Members[0];
            root      = root.ReplaceNode(classNode, classNode.WithMembers(new SyntaxList <MemberDeclarationSyntax>(classNode.Members.Cast <MethodDeclarationSyntax>().Skip(2))));

            return(root.NormalizeWhitespace().GetText());
        }
Esempio n. 4
0
        public SourceText GetTableTypeText(Definition.Schema schema, Definition.TableType tableType)
        {
            var rootDir     = _output.GetOutputRootDir();
            var fileContent = File.ReadAllText(Path.Combine(rootDir.FullName, "DataContext", "TableTypes", "TableType.cs"));

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

            // 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));
            }

            // If its an extension, add usings for the lib
            if (_configFile.Config.Project.Role.Kind == ERoleKind.Extension)
            {
                var libModelUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"{_configFile.Config.Project.Role.LibNamespace}.TableTypes"));
                root = root.AddUsings(libModelUsingDirective).NormalizeWhitespace();
            }

            var nsNode = (NamespaceDeclarationSyntax)root.Members[0];

            // Replace ClassName
            var classNode       = (ClassDeclarationSyntax)nsNode.Members[0];
            var classIdentifier = SyntaxFactory.ParseToken($"{classNode.Identifier.ValueText.Replace("TableType", $"{GetTypeNameForTableType(tableType)}")} ");

            classNode = classNode.WithIdentifier(classIdentifier);

            root = root.ReplaceNode(nsNode, nsNode.AddMembers(classNode));

            // Create Properties
            if (tableType.Columns != null)
            {
                foreach (var column in tableType.Columns)
                {
                    nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
                    classNode = (ClassDeclarationSyntax)nsNode.Members[1];
                    var propertyNode = (PropertyDeclarationSyntax)classNode.Members[0];

                    var propertyIdentifier = SyntaxFactory.ParseToken($" {column.Name} ");

                    propertyNode = propertyNode
                                   .WithType(ParseTypeFromSqlDbTypeName(column.SqlTypeName, column.IsNullable ?? false));

                    propertyNode = propertyNode
                                   .WithIdentifier(propertyIdentifier);

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

                        propertyNode = propertyNode.WithAttributeLists(attributes);
                    }

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

            // Remove template Property
            nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
            classNode = (ClassDeclarationSyntax)nsNode.Members[1];
            root      = root.ReplaceNode(classNode, classNode.WithMembers(new SyntaxList <MemberDeclarationSyntax>(classNode.Members.Cast <PropertyDeclarationSyntax>().Skip(1))));

            // Remove template Class
            nsNode = (NamespaceDeclarationSyntax)root.Members[0];
            root   = root.ReplaceNode(nsNode, nsNode.WithMembers(new SyntaxList <MemberDeclarationSyntax>(nsNode.Members.Cast <ClassDeclarationSyntax>().Skip(1))));

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