private static IEnumerable <AttributeListSyntax> BuildColumnAttributes(IDatabaseColumn column, string propertyName)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (propertyName.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            if (propertyName == column.Name.LocalName)
            {
                return(Array.Empty <AttributeListSyntax>());
            }

            return(new[]
            {
                AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(AliasAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(column.Name.LocalName)))))))
                    )
            });
        }
        private static IEnumerable <AttributeListSyntax> BuildClassAttributes(IRelationalDatabaseTable table, string className)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (className.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(className));
            }

            var attributes = new List <AttributeListSyntax>();

            if (className != table.Name.LocalName)
            {
                var attributeArguments = new List <AttributeArgumentSyntax>
                {
                    AttributeArgument(
                        LiteralExpression(
                            SyntaxKind.StringLiteralExpression,
                            Literal(table.Name.LocalName)))
                };

                var schemaName = table.Name.Schema;
                if (!schemaName.IsNullOrWhiteSpace())
                {
                    var schemaArgument = AttributeArgument(
                        AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            IdentifierName(nameof(TableAttribute.Schema)),
                            Token(SyntaxKind.EqualsToken),
                            LiteralExpression(
                                SyntaxKind.StringLiteralExpression,
                                Literal(schemaName))));
                    attributeArguments.Add(schemaArgument);
                }

                var tableAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(TableAttribute)),
                            AttributeArgumentList(
                                SeparatedList(attributeArguments)))));
                attributes.Add(tableAttribute);
            }

            return(attributes);
        }
        private static IEnumerable <AttributeListSyntax> BuildClassAttributes(IDatabaseView view, string className)
        {
            if (view == null)
            {
                throw new ArgumentNullException(nameof(view));
            }
            if (className.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(className));
            }

            var attributes = new List <AttributeListSyntax>();

            var schemaName = view.Name.Schema;

            if (!schemaName.IsNullOrWhiteSpace())
            {
                var schemaAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(SchemaAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(schemaName))))))));
                attributes.Add(schemaAttribute);
            }

            if (className != view.Name.LocalName)
            {
                var aliasAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(AliasAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(view.Name.LocalName))))))));
                attributes.Add(aliasAttribute);
            }

            return(attributes);
        }
        private static IEnumerable <AttributeListSyntax> BuildColumnAttributes(IDatabaseColumn column, string propertyName)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (propertyName.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            var columnAttributeArgs = new List <AttributeArgumentSyntax>();

            if (propertyName != column.Name.LocalName)
            {
                var quotedColumnName = LiteralExpression(
                    SyntaxKind.StringLiteralExpression,
                    Literal(column.Name.LocalName));
                columnAttributeArgs.Add(AttributeArgument(quotedColumnName));
            }
            columnAttributeArgs.Add(
                AttributeArgument(
                    AssignmentExpression(
                        SyntaxKind.SimpleAssignmentExpression,
                        IdentifierName(nameof(ColumnAttribute.TypeName)),
                        Token(SyntaxKind.EqualsToken),
                        LiteralExpression(
                            SyntaxKind.StringLiteralExpression,
                            Literal(column.Type.TypeName.LocalName)))));

            return(new[]
            {
                AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(ColumnAttribute)),
                            AttributeArgumentList(
                                SeparatedList(columnAttributeArgs)))))
            });
        }
        private static IEnumerable <AttributeListSyntax> BuildColumnAttributes(IDatabaseColumn column, string propertyName)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (propertyName.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            var attributes = new List <AttributeListSyntax>();
            var clrType    = column.Type.ClrType;

            var isConstrainedType = clrType == typeof(string) || clrType == typeof(byte[]);

            if (isConstrainedType && column.Type.MaxLength > 0)
            {
                var maxLengthAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(MaxLengthAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            Literal(column.Type.MaxLength))))))));
                attributes.Add(maxLengthAttribute);
            }

            if (!clrType.IsValueType && !column.IsNullable)
            {
                var requiredAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(RequiredAttribute)))));
                attributes.Add(requiredAttribute);
            }

            column.AutoIncrement.IfSome(_ =>
            {
                var databaseGeneratedAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(DatabaseGeneratedAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        MemberAccessExpression(
                                            SyntaxKind.SimpleMemberAccessExpression,
                                            IdentifierName(nameof(DatabaseGeneratedOption)),
                                            IdentifierName(nameof(DatabaseGeneratedOption.Identity)))))))));
                attributes.Add(databaseGeneratedAttribute);
            });

            var columnAttributeArgs = new List <AttributeArgumentSyntax>();

            if (propertyName != column.Name.LocalName)
            {
                var quotedColumnName = LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(column.Name.LocalName));
                columnAttributeArgs.Add(AttributeArgument(quotedColumnName));
            }
            columnAttributeArgs.Add(
                AttributeArgument(
                    AssignmentExpression(
                        SyntaxKind.SimpleAssignmentExpression,
                        IdentifierName(nameof(ColumnAttribute.TypeName)),
                        Token(SyntaxKind.EqualsToken),
                        LiteralExpression(
                            SyntaxKind.StringLiteralExpression,
                            Literal(column.Type.TypeName.LocalName))))
                );

            var columnAttribute = AttributeList(
                SingletonSeparatedList(
                    Attribute(
                        SyntaxUtilities.AttributeName(nameof(ColumnAttribute)),
                        AttributeArgumentList(
                            SeparatedList(columnAttributeArgs)))));

            attributes.Add(columnAttribute);

            return(attributes);
        }
        private IEnumerable <AttributeListSyntax> BuildColumnAttributes(IRelationalDatabaseTable table, IDatabaseColumn column, string propertyName)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (propertyName.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            var attributes = new List <AttributeListSyntax>();
            var clrType    = column.Type.ClrType;

            if (clrType == typeof(string) && column.Type.MaxLength > 0)
            {
                var maxLengthAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(StringLengthAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            Literal(column.Type.MaxLength))))))));
                attributes.Add(maxLengthAttribute);
            }

            if (!clrType.IsValueType && !column.IsNullable)
            {
                var requiredAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(RequiredAttribute)))));
                attributes.Add(requiredAttribute);
            }

            var isPrimaryKey = ColumnIsPrimaryKey(table, column);

            if (isPrimaryKey)
            {
                var primaryKeyAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(PrimaryKeyAttribute)))));
                attributes.Add(primaryKeyAttribute);
            }

            if (column.AutoIncrement.IsSome)
            {
                var autoIncrementAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(AutoIncrementAttribute)))));
                attributes.Add(autoIncrementAttribute);
            }

            var isNonUniqueIndex = ColumnIsNonUniqueIndex(table, column);
            var isUniqueIndex    = ColumnIsUniqueIndex(table, column);
            var isIndex          = isNonUniqueIndex || isUniqueIndex;

            if (isIndex)
            {
                var indexAttribute = Attribute(
                    SyntaxUtilities.AttributeName(nameof(IndexAttribute))
                    );
                var indexAttributeList = AttributeList(SingletonSeparatedList(indexAttribute));

                if (isNonUniqueIndex)
                {
                    attributes.Add(indexAttributeList);
                }
                else
                {
                    var uniqueIndexAttribute = indexAttribute
                                               .WithArgumentList(
                        AttributeArgumentList(
                            SingletonSeparatedList(
                                AttributeArgument(
                                    LiteralExpression(SyntaxKind.TrueLiteralExpression)))));

                    var uniqueIndexAttributeList = AttributeList(SingletonSeparatedList(uniqueIndexAttribute));
                    attributes.Add(uniqueIndexAttributeList);
                }
            }

            var isUniqueKey = ColumnIsUniqueKey(table, column);

            if (isUniqueKey)
            {
                var uniqueKeyAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(UniqueAttribute)))));
                attributes.Add(uniqueKeyAttribute);
            }

            column.DefaultValue.IfSome(def =>
            {
                var defaultAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(DefaultAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(def))))))));
                attributes.Add(defaultAttribute);
            });

            var isForeignKey = ColumnIsForeignKey(table, column);

            if (isForeignKey)
            {
                var relationalKey = ColumnRelationalKey(table, column);
                if (relationalKey == null)
                {
                    throw new InvalidOperationException("Could not find parent key for foreign key relationship. Expected to find one for " + column.Name.LocalName + "." + column.Name.LocalName);
                }

                var parentTable     = relationalKey.ParentTable;
                var parentClassName = NameTranslator.TableToClassName(parentTable);
                // TODO check that this is not implicit -- i.e. there is a naming convention applied
                //      so explicitly declaring via [References(...)] may not be necessary

                var fkAttributeArgs = new List <AttributeArgumentSyntax>
                {
                    AttributeArgument(TypeOfExpression(ParseTypeName(parentClassName)))
                };

                relationalKey.ChildKey.Name.IfSome(fkName =>
                {
                    var foreignKeyNameArg = AttributeArgument(
                        AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            IdentifierName(nameof(ForeignKeyAttribute.ForeignKeyName)),
                            Token(SyntaxKind.EqualsToken),
                            LiteralExpression(
                                SyntaxKind.StringLiteralExpression,
                                Literal(fkName.LocalName))));
                    fkAttributeArgs.Add(foreignKeyNameArg);
                });

                if (relationalKey.DeleteAction != ReferentialAction.NoAction)
                {
                    var deleteAction          = ForeignKeyAction[relationalKey.DeleteAction];
                    var foreignKeyOnDeleteArg = AttributeArgument(
                        AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            IdentifierName(nameof(ForeignKeyAttribute.OnDelete)),
                            Token(SyntaxKind.EqualsToken),
                            LiteralExpression(
                                SyntaxKind.StringLiteralExpression,
                                Literal(deleteAction))));
                    fkAttributeArgs.Add(foreignKeyOnDeleteArg);
                }

                if (relationalKey.UpdateAction != ReferentialAction.NoAction)
                {
                    var updateAction          = ForeignKeyAction[relationalKey.UpdateAction];
                    var foreignKeyOnUpdateArg = AttributeArgument(
                        AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            IdentifierName(nameof(ForeignKeyAttribute.OnUpdate)),
                            Token(SyntaxKind.EqualsToken),
                            LiteralExpression(
                                SyntaxKind.StringLiteralExpression,
                                Literal(updateAction))));
                    fkAttributeArgs.Add(foreignKeyOnUpdateArg);
                }

                var foreignKeyAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(ForeignKeyAttribute)),
                            AttributeArgumentList(SeparatedList(fkAttributeArgs)))));
                attributes.Add(foreignKeyAttribute);
            }

            if (propertyName != column.Name.LocalName)
            {
                var aliasAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(AliasAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(column.Name.LocalName))))))));
                attributes.Add(aliasAttribute);
            }

            return(attributes);
        }
        private IEnumerable <AttributeListSyntax> BuildClassAttributes(IRelationalDatabaseTable table, string className)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (className.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(className));
            }

            var attributes = new List <AttributeListSyntax>();

            var schemaName = table.Name.Schema;

            if (!schemaName.IsNullOrWhiteSpace())
            {
                var schemaAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(SchemaAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(schemaName))))))));
                attributes.Add(schemaAttribute);
            }

            if (className != table.Name.LocalName)
            {
                var aliasAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(AliasAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(table.Name.LocalName))))))));
                attributes.Add(aliasAttribute);
            }

            var multiColumnUniqueKeys = table.UniqueKeys.Where(uk => uk.Columns.Skip(1).Any()).ToList();

            foreach (var uniqueKey in multiColumnUniqueKeys)
            {
                var columnNames = uniqueKey.Columns
                                  .Select(c => NameTranslator.ColumnToPropertyName(className, c.Name.LocalName))
                                  .Select(p => AttributeArgument(
                                              InvocationExpression(
                                                  IdentifierName(
                                                      Identifier(
                                                          TriviaList(),
                                                          SyntaxKind.NameOfKeyword,
                                                          "nameof",
                                                          "nameof",
                                                          TriviaList())),
                                                  ArgumentList(
                                                      SingletonSeparatedList(
                                                          Argument(
                                                              IdentifierName(p)))))));

                var uniqueConstraintAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(UniqueConstraintAttribute)),
                            AttributeArgumentList(
                                SeparatedList(columnNames)))));
                attributes.Add(uniqueConstraintAttribute);
            }

            var multiColumnIndexes = table.Indexes.Where(ix => ix.Columns.Skip(1).Any()).ToList();

            foreach (var index in multiColumnIndexes)
            {
                var indexColumns     = index.Columns;
                var dependentColumns = indexColumns.SelectMany(ic => ic.DependentColumns).ToList();
                if (dependentColumns.Count > indexColumns.Count)
                {
                    continue;
                }

                var attrParams = dependentColumns
                                 .Select(c => NameTranslator.ColumnToPropertyName(className, c.Name.LocalName))
                                 .Select(p => AttributeArgument(
                                             InvocationExpression(
                                                 IdentifierName(
                                                     Identifier(
                                                         TriviaList(),
                                                         SyntaxKind.NameOfKeyword,
                                                         "nameof",
                                                         "nameof",
                                                         TriviaList())),
                                                 ArgumentList(
                                                     SingletonSeparatedList(
                                                         Argument(
                                                             IdentifierName(p))))
                                                 )
                                             ))
                                 .ToList();

                if (index.IsUnique)
                {
                    var uniqueTrueArgument = AttributeArgument(
                        LiteralExpression(SyntaxKind.TrueLiteralExpression)
                        );
                    attrParams = new[] { uniqueTrueArgument }.Concat(attrParams).ToList();
                }

                var compositeIndexAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(CompositeIndexAttribute)),
                            AttributeArgumentList(
                                SeparatedList(attrParams)))));
                attributes.Add(compositeIndexAttribute);
            }

            return(attributes);
        }