Example #1
0
        protected override void GenerateManyToMany(ITable table)
        {
            var tableNamespace = TableNamespace(table);
            var tableClassName = TableClassName(table);
            var tableClass     = GenerationContext.FindClass(tableClassName, tableNamespace);

            var manyToManyList = table.ManyToMany().ToList();

            manyToManyList.ForEach(fk =>
            {
                if (!TablesToGenerate.Contains(fk.ForeignKeyColumn.Table))
                {
                    return;
                }

                // get the poco of the many to many.
                var manyToManyPocoFullClass = TableClassFullName(fk.ForeignKeyColumn.Table);

                // pluralize this name.
                var propName = Pluralize(fk.ForeignKeyColumn.Table.Name);
                propName     = tableClass.GetUniqueMemberName(propName);

                // the type of the property.
                var propType     = $"System.Collections.Generic.ICollection<{manyToManyPocoFullClass}>";
                var defaultValue = $"new {CollectionInstanceType()}<{manyToManyPocoFullClass}>()";

                // generate property :)
                tableClass.Property(p => p.Type(propType).Name(propName).DefaultValue(defaultValue).Comment("Many to Many").Meta(fk));
            });
        }
        protected virtual void GenerateSequenceMethods()
        {
            if (!Options.GenerateContextSequenceMethods)
            {
                return;
            }

            var contextNamespace = ContextNamespace();
            var contextClassName = ContextClassName();
            var contextClass     = GenerationContext.FindClass(contextClassName, contextNamespace);

            SequenceToGenerate.ForEach(sequence =>
            {
                var dataType   = DataTypeResolver.ResolveType(sequence);
                var outputType = dataType.GetOutputType();

                var methodName = $"GetNextValueFor{sequence.Name}";

                contextClass.Method(m =>
                {
                    m.AccessModifier(AccessModifiers.Public)
                    .ReturnType(outputType)
                    .Name(methodName);

                    GenerateGetNextSequenceLines(m, outputType, sequence);
                });
            });
        }
        protected virtual void GenerateForeignKeys(ITable table)
        {
            var tableNamespace = TableNamespace(table);
            var tableClassName = TableClassName(table);
            var tableClass     = GenerationContext.FindClass(tableClassName, tableNamespace);

            table.ForeignKeys.ForEach(fk =>
            {
                if (!TablesToGenerate.Contains(fk.PrimaryKeyColumn.Table))
                {
                    return;
                }

                var propName = ForeignKeyPropertyName(fk);
                if (tableClass.HasMemberWithName(propName))
                {
                    var tempPropName = ForeignKeyPropertyName(fk, true);
                    if (!tableClass.HasMemberWithName(tempPropName))
                    {
                        propName = tempPropName;
                    }
                }

                propName = tableClass.GetUniqueMemberName(propName);
                var foreignKeyTypeName = TableClassFullName(fk.PrimaryKeyColumn.Table);
                tableClass.Property(foreignKeyProp => foreignKeyProp.Virtual(ForeignKeysShouldBeVirtual()).Type(foreignKeyTypeName).Name(propName).Comment("Foreign Key").Meta(fk));
            });
        }
        protected virtual void GenerateHasMany(ITable table)
        {
            var tableNamespace = TableNamespace(table);
            var tableClassName = TableClassName(table);
            var tableClass     = GenerationContext.FindClass(tableClassName, tableNamespace);

            var hasManyList = table.HasMany().ToList();

            hasManyList.ForEach(fk =>
            {
                if (!TablesToGenerate.Contains(fk.ForeignKeyColumn.Table))
                {
                    return;
                }

                var hasMoreThanOne = table.HasMany().Count(t => t.ForeignKeyColumn.Table == fk.ForeignKeyColumn.Table) > 1;
                var propName       = HasManyPropertyName(fk, hasMoreThanOne);

                propName         = tableClass.GetUniqueMemberName(propName);
                var pocoType     = TableClassFullName(fk.ForeignKeyColumn.Table);
                var propType     = $"System.Collections.Generic.ICollection<{pocoType}>";
                var defaultValue = $"new {CollectionInstanceType()}<{pocoType}>()";
                tableClass.Property(p => p.Virtual(HasManyShouldBeVirtual()).Type(propType).Name(propName).DefaultValue(defaultValue).Comment("Has Many").Meta(fk));
            });
        }
        protected override void GenerateManyToMany(ITable table)
        {
            var tableNamespace = TableNamespace(table);
            var tableClassName = TableClassName(table);
            var tableClass     = GenerationContext.FindClass(tableClassName, tableNamespace);

            var manyToManyList = table.ManyToMany().ToList();

            manyToManyList.ForEach(fk =>
            {
                // get the other foreign key of this many to many.
                var otherFk = fk.ForeignKeyColumn.Table.ForeignKeys.FirstOrDefault(t => t != fk);

                // other table attached to this many to many.
                var otherPk = otherFk.PrimaryKeyColumn.Table;

                // skip if other table is not being generated.
                if (!TablesToGenerate.Contains(otherPk))
                {
                    return;
                }

                // pluralize this name.
                var propName = ManyToManyPropertyName(table, fk, otherFk);
                propName     = tableClass.GetUniqueMemberName(propName);

                // the type of the property.
                var pocoType     = TableClassFullName(otherPk);
                var propType     = $"System.Collections.Generic.ICollection<{pocoType}>";
                var defaultValue = $"new {CollectionInstanceType()}<{pocoType}>()";

                // generate property :)
                tableClass.Property(p => p.Virtual(true).Type(propType).Name(propName).DefaultValue(defaultValue).Comment("Many to Many").Meta(Tuple.Create(NavigationKind.ManyToMany, fk)));
            });
        }
        protected virtual void GenerateModelInterface(ITable table, FileBuilder fileBuilder)
        {
            if (!Options.GenerateModelsInterfaces)
            {
                return;
            }

            var tableNamespace     = TableNamespace(table);
            var tableClassName     = TableClassName(table);
            var modelInterfaceName = ModelInterfaceName(table);
            var tableClassFullName = TableClassFullName(table);
            var tableClass         = GenerationContext.FindClass(tableClassName, tableNamespace);


            if (!Options.OutputToSingleFile)
            {
                var filePath = $"{Options.OutputDir}{Path.DirectorySeparatorChar}{modelInterfaceName}.generated.cs";
                fileBuilder.Path(filePath);
            }

            fileBuilder.Namespace(tableNamespace, true, ns =>
            {
                ns.Interface(modelInterface =>
                {
                    // set basic info.
                    modelInterface.Partial(true).Name(modelInterfaceName);

                    // set properties.
                    table.Columns.ForEach(column =>
                    {
                        modelInterface.Property(columnProperty =>
                        {
                            var type                = DataTypeResolver.ResolveType(column);
                            var typeName            = type.GetOutputType();
                            bool isPropertyNullable = column.IsNullable || Options.GenerateModelPropertyAsNullable;
                            if (type.IsValueType && isPropertyNullable)
                            {
                                typeName = $"{typeName}?";
                            }

                            columnProperty
                            .AccessModifier(AccessModifiers.Omit)
                            .Name(column.Name)
                            .Type(typeName)
                            .Meta(column);
                        });
                    });
                });
            });
        }
        protected virtual void GenerateOneToOnes(ITable table)
        {
            var tableNamespace = TableNamespace(table);
            var tableClassName = TableClassName(table);
            var tableClass     = GenerationContext.FindClass(tableClassName, tableNamespace);

            table.OneToOne().ToList().ForEach(fk =>
            {
                if (!TablesToGenerate.Contains(fk.ForeignKeyColumn.Table))
                {
                    return;
                }

                var propName = OneToOnePropertyName(fk);
                propName     = tableClass.GetUniqueMemberName(propName);
                var propType = TableClassFullName(fk.ForeignKeyColumn.Table);
                tableClass.Property(p => p.Virtual(OneToShouldBeVirtual()).Type(propType).Name(propName).Comment("One to One").Meta(fk));
            });
        }
Example #8
0
        protected virtual void AddFluentToMethod(MethodBuilder methodBuilder, ITable table)
        {
            var tableNamespace     = TableNamespace(table);
            var tableClassName     = TableClassName(table);
            var tableFullClassName = TableClassFullName(table);
            var tableClass         = GenerationContext.FindClass(tableClassName, tableNamespace);

            var fluentExpression = MultiLineLambdaExpression.Create()
                                   .Parameter(p => p.Name("entity"))
                                   .RawLine($"entity.{ToTableFluent(table)}");
            //.RawLine($"entity.ToTable(\"{table.Name}\", \"{table.Schema}\")");

            var pks             = table.Columns.Where(t => t.IsPrimaryKey);
            var hasCompositeKey = pks.Count() > 1;

            ; if (hasCompositeKey)
            {
                var def = string.Join(", ", pks.Select(pk =>
                {
                    var pkProp = tableClass.FindByMeta <PropertyBuilder>(pk);
                    return($"t.{pkProp.GetName()}");
                }));
                fluentExpression.RawLine($"entity.HasKey(t => new {{ {def} }})");
            }
            else
            {
                var pk     = pks.First();
                var pkProp = tableClass.FindByMeta <PropertyBuilder>(pk);
                fluentExpression.RawLine($"entity.HasKey(t => t.{pkProp.GetName()})");
            }

            table.Indexes.ForEach(i =>
            {
                if (!ShouldGenerateIndex(i))
                {
                    return;
                }

                var line = RawLineBuilder.Create();

                string rightExpr;
                if (i.Columns.Count == 1)
                {
                    var indexProp = tableClass.FindByMeta <PropertyBuilder>(i.Columns.First());
                    rightExpr     = $"t.{indexProp.GetName()}";
                }
                else
                {
                    var cols  = string.Join(", ", i.Columns.Select(t => $"t.{tableClass.FindByMeta<PropertyBuilder>(t).GetName()}"));
                    rightExpr = $"new {{ {cols} }}";
                }

                line.Append($"entity.HasIndex(t => {rightExpr})");
                line.Append($"\n\t.HasName(\"{i.Name}\")");
                if (i.IsUnique)
                {
                    line.Append("\n\t.IsUnique()");
                }

                OnBeforeIndexLineAdded(line, i);

                fluentExpression.Add(line);
            });

            table.Columns.ForEach(c =>
            {
                var columnProp = tableClass.FindByMeta <PropertyBuilder>(c);
                var line       = RawLineBuilder.Create();
                line.Append($"entity.Property(t => t.{columnProp.GetName()})");
                line.Append($".HasColumnType(\"{FluentColumnType(c)}\")");

                if (c.IsPrimaryKey)
                {
                    if (c.IsAutoIncrement)
                    {
                        line.Append(".ValueGeneratedOnAdd()");
                    }
                    else
                    {
                        line.Append(".ValueGeneratedNever()");
                    }
                }
                else if (!string.IsNullOrWhiteSpace(c.DefaultValue))
                {
                    line.Append($".HasDefaultValueSql(\"{c.DefaultValue}\")");
                }

                if (!c.IsNullable)
                {
                    line.Append(".IsRequired()");
                }

                if (c.CharacterMaximumLength.HasValue && c.CharacterMaximumLength != -1)
                {
                    line.Append($".HasMaxLength({c.CharacterMaximumLength})");
                }

                if (DataTypeResolver.IsString(c) && !DataTypeResolver.IsUnicode(c))
                {
                    line.Append(".IsUnicode(false)");
                }

                fluentExpression.Add(line);
            });

            table.ForeignKeys.ForEach(fk =>
            {
                if (!TablesToGenerate.Contains(fk.PrimaryKeyColumn.Table))
                {
                    return;
                }

                var fkProp           = tableClass.FindByMeta <PropertyBuilder>(fk);
                var fkColumnProp     = tableClass.FindByMeta <PropertyBuilder>(fk.ForeignKeyColumn);
                var fkTableNamespace = TableNamespace(fk.PrimaryKeyColumn.Table);
                var fkTableClassName = TableClassName(fk.PrimaryKeyColumn.Table);
                var fkTableClass     = GenerationContext.FindClass(fkTableClassName, fkTableNamespace);
                var reverseProp      = fkTableClass.FindByMeta <PropertyBuilder>(fk);

                var line = RawLineBuilder.Create();

                line.Append($"entity.HasOne(t => t.{fkProp.GetName()})");

                if (!fk.IsOneToOne())
                {
                    line.Append($"\n\t.WithMany(t => t.{reverseProp.GetName()})");
                    line.Append($"\n\t.HasForeignKey(t => t.{fkColumnProp.GetName()})");
                }
                else
                {
                    line.Append($"\n\t.WithOne(t => t.{reverseProp.GetName()})");
                    line.Append($"\n\t.HasForeignKey<{tableFullClassName}>(t => t.{fkColumnProp.GetName()})");
                }

                if (IsCascade(fk.DeleteCascadeAction))
                {
                    line.Append("\n\t.OnDelete(DeleteBehavior.Delete)");
                }
                else if (IsSetNull(fk.DeleteCascadeAction))
                {
                    line.Append("\n\t.OnDelete(DeleteBehavior.SetNull)");
                }
                else
                {
                    line.Append("\n\t.OnDelete(DeleteBehavior.ClientSetNull)");
                }

                line.Append($"\n\t.HasConstraintName(\"{fk.Name}\")");

                line.Comment("Foreign Key");
                fluentExpression.Add(line);
            });


            var modelFluentLine = $"modelBuilder.Entity<{tableFullClassName}>({fluentExpression.GenerateInline()})";

            methodBuilder.Add(RawLineBuilder.Create(modelFluentLine));
            methodBuilder.AddEmptyLine();
        }
        protected virtual void GenerateModel(ITable table, FileBuilder fileBuilder)
        {
            if (!Options.GenerateModels)
            {
                return;
            }

            var tableNamespace     = TableNamespace(table);
            var tableClassName     = TableClassName(table);
            var modelClassName     = ModelClassName(table);
            var modelInterfaceName = ModelInterfaceName(table);
            var tableClassFullName = TableClassFullName(table);
            var tableClass         = GenerationContext.FindClass(tableClassName, tableNamespace);


            if (!Options.OutputToSingleFile)
            {
                var filePath = $"{Options.OutputDir}{Path.DirectorySeparatorChar}{modelClassName}.generated.cs";
                fileBuilder.Path(filePath);
            }

            fileBuilder.Namespace(tableNamespace, true, ns =>
            {
                ns.Class(modelClass =>
                {
                    // set basic info.
                    modelClass.Partial(true).Name(modelClassName);

                    if (Options.GenerateModelsInterfaces)
                    {
                        modelClass.Inherits(modelInterfaceName);
                    }

                    Options?.ModelInheritances.ForEach(mi =>
                    {
                        modelClass.Inherits(ReplaceMetas(mi, table));
                    });


                    MethodBuilder from = null;
                    MethodBuilder to   = null;

                    modelClass.Method(m =>
                    {
                        m
                        .AccessModifier(AccessModifiers.Public)
                        .Virtual(true)
                        .ReturnType("void")
                        .Name("From")
                        .Parameter(p => p.Type(tableClassFullName).Name("entity"));
                        from = m;
                    });

                    modelClass.Method(m =>
                    {
                        m
                        .AccessModifier(AccessModifiers.Public)
                        .Virtual(true)
                        .ReturnType("void")
                        .Name("To")
                        .Parameter(p => p.Type(tableClassFullName).Name("entity"));
                        to = m;
                    });

                    modelClass.Method(m => m
                                      .Virtual(true)
                                      .ReturnType("System.Type")
                                      .Name("GetContextType")
                                      .RawLine($"return typeof({ContextFullClassName()})")
                                      );

                    modelClass.Method(m => m
                                      .ReturnType("System.Type")
                                      .Name("GetEntityType")
                                      .RawLine($"return typeof({tableClassFullName})")
                                      );

                    // set properties.
                    table.Columns.ForEach(column =>
                    {
                        modelClass.Property(columnProperty =>
                        {
                            var type                = DataTypeResolver.ResolveType(column);
                            var typeName            = type.GetOutputType();
                            bool isPropertyNullable = column.IsNullable || Options.GenerateModelPropertyAsNullable;
                            if (type.IsValueType && isPropertyNullable)
                            {
                                typeName = $"{typeName}?";
                            }

                            columnProperty
                            .Virtual(true)
                            .Name(column.Name)
                            .Type(typeName)
                            .Meta(column);

                            from.RawLine($"{column.Name} = entity.{column.Name}");

                            if (isPropertyNullable && !column.IsNullable)
                            {
                                var matchingProp = tableClass.FindByMeta <PropertyBuilder>(column);
                                var ternary      = TernaryBuilder
                                                   .Create()
                                                   .RawCondition(rc => rc.Condition($"{column.Name} != null"))
                                                   .True(RawInlineBuilder.Create($"entity.{column.Name} = ({matchingProp.GetTypeName()}){column.Name}"))
                                                   .False(RawInlineBuilder.Create($"entity.{column.Name} = default({matchingProp.GetTypeName()})"));

                                to.RawLine($"entity.{column.Name} = {ternary.GenerateInline()}");
                            }
                            else
                            {
                                to.RawLine($"entity.{column.Name} = {column.Name}");
                            }
                        });
                    });
                });
            });
        }
        // TODO refactor. move to SQL SERVER EF6
        /// <summary>
        /// //method.RawLine($"return Database.SqlQuery<{outputType}>(\"SELECT NEXT VALUE FOR [{sequence.Schema}].[{sequence.Name}];\").First()");
        /// </summary>
        /// <param name="method"></param>
        /// <param name="outputType"></param>
        /// <param name="sequence"></param>
        //protected abstract void GenerateGetNextSequenceLines(MethodBuilder method, string outputType, ISequence sequence);



        private void GenerateEntityFluentConfiguration(ITable table)
        {
            var tableNamespace = TableNamespace(table);
            var tableFluentConfigurationClassName = $"{TableClassName(table)}{Options.FluentConfigurationClassSuffix}";
            var tableClassName     = TableClassName(table);
            var tableClassFullName = TableClassFullName(table);
            var entityClass        = GenerationContext.FindClass(tableClassName, tableNamespace);
            var contextNamespace   = ContextNamespace();

            // set the path.
            var outputDir = Options.ContextOutputDir ?? Options.OutputDir;
            var fileName  = Options.ContextOutputSingleFileName ?? Options.OutputSingleFileName ?? $"{tableFluentConfigurationClassName}.generated.cs";
            var path      = $"{outputDir}{Path.DirectorySeparatorChar}{fileName}";

            GenerationContext.File(path, fileBuilder =>
            {
                // set the namespace.
                fileBuilder.Namespace(contextNamespace, true, ns =>
                {
                    ns.Class(tableFluentConfigurationClassName, true, fluentConfigClass =>
                    {
                        fluentConfigClass
                        .Partial(true)
                        .Inherits($"System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<{tableClassFullName}>")
                        .Constructor(constructor =>
                        {
                            constructor.AddComment("Table mapping & keys");

                            // to table mapping.
                            constructor.RawLine(ToTableFluent(table));

                            if (table.Columns.Count(t => t.IsPrimaryKey) > 1)
                            {
                                //HasKey(x => new { x.PurchaseOrderId, x.RequiredDocumentId });
                                var props = string.Join(", ", table.Columns
                                                        .Where(t => t.IsPrimaryKey)
                                                        .OrderBy(t => t.PrimaryKeyOrder)
                                                        .Select(t => $"x.{entityClass.FindByMeta<PropertyBuilder>(t).GetName()}"));

                                var line = $"HasKey(x => new {{ {props} }})";
                                constructor.RawLine(line);
                            }
                            else
                            {
                                // pk mapping.
                                var pk     = table.Columns.FirstOrDefault(t => t.IsPrimaryKey);
                                var pkProp = entityClass.FindByMeta <PropertyBuilder>(pk);
                                constructor.RawLine($"HasKey(t => t.{pkProp.GetName()})");
                            }

                            constructor.AddComment("Columns");

                            // columns mapping.
                            table.Columns.ForEach(column =>
                            {
                                var columnProp = entityClass.FindByMeta <PropertyBuilder>(column);
                                var columnLine = RawLineBuilder.Create();
                                columnLine.Append($"Property(t => t.{columnProp.GetName()})");
                                columnLine.Append($".HasColumnName(\"{column.Name}\")");

                                if (column.IsNullable)
                                {
                                    columnLine.Append(".IsOptional()");
                                }
                                else
                                {
                                    columnLine.Append(".IsRequired()");
                                }

                                columnLine.Append($".HasColumnType(\"{column.DataType}\")");

                                if (column.IsPrimaryKey)
                                {
                                    if (IsGenerateOptionIdentity(column))
                                    {
                                        columnLine.Append(".HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)");
                                    }
                                    else
                                    {
                                        columnLine.Append(".HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)");
                                    }

                                    /*
                                     * // TODO make overridable class method here called IsGenerateOptionIdentity(IColumn)
                                     * if (column.IsAutoIncrement)
                                     *  columnLine.Append(".HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)");
                                     * else if (column.DataType == "uniqueidentifier" && column.DefaultValue.IndexOf("newsequentialid", StringComparison.InvariantCultureIgnoreCase) > -1)
                                     *  columnLine.Append(".HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)");
                                     * else
                                     *  columnLine.Append(".HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)");
                                     */
                                }

                                if (column.CharacterMaximumLength.HasValue && column.CharacterMaximumLength != -1)
                                {
                                    columnLine.Append($".HasMaxLength({column.CharacterMaximumLength})");
                                }

                                if (DataTypeResolver.IsFixLength(column))
                                {
                                    columnLine.Append(".IsFixedLength()");
                                }

                                if (DataTypeResolver.IsString(column) && !DataTypeResolver.IsUnicode(column))
                                {
                                    columnLine.Append(".IsUnicode(false)");
                                }

                                if (column.NumericPrecision.HasValue && column.NumericScale.HasValue && column.NumericScale != 0)
                                {
                                    columnLine.Append($".HasPrecision({column.NumericPrecision}, {column.NumericScale})");
                                }


                                constructor.Add(columnLine);
                            });

                            constructor.AddComment("Navigations");
                            table.ForeignKeys.ForEach(fk =>
                            {
                                var fkProp       = FindNavigation(entityClass, fk);
                                var fkColumnProp = entityClass.FindByMeta <PropertyBuilder>(fk.ForeignKeyColumn);

                                // if null meaning its being filtered. (excluded table from generation)
                                if (fkProp != null)
                                {
                                    var line             = RawLineBuilder.Create();
                                    var primaryNamespace = TableNamespace(fk.PrimaryKeyColumn.Table);
                                    var primaryClassName = TableClassName(fk.PrimaryKeyColumn.Table);
                                    var primaryEntity    = GenerationContext.FindClass(primaryClassName, primaryNamespace);

                                    PropertyBuilder reverseNav;
                                    if (fk.PrimaryKeyColumn.Table == fk.ForeignKeyColumn.Table)
                                    {
                                        reverseNav = FindNavigation(primaryEntity, fk, NavigationKind.HasMany);
                                    }
                                    else
                                    {
                                        reverseNav = FindNavigation(primaryEntity, fk);
                                    }

                                    if (fk.ForeignKeyColumn.IsNullable)
                                    {
                                        line.Append($"HasOptional(t => t.{fkProp.GetName()})");
                                    }
                                    else
                                    {
                                        line.Append($"HasRequired(t => t.{fkProp.GetName()})");
                                    }

                                    if (fk.IsOneToOne())
                                    {
                                        line.Append($".WithOptional(t => t.{reverseNav.GetName()})");
                                    }
                                    else
                                    {
                                        line.Append($".WithMany(t => t.{reverseNav.GetName()})");
                                        line.Append($".HasForeignKey(t => t.{fkColumnProp.GetName()})");
                                    }
                                    constructor.Add(line);
                                }
                            });

                            constructor.AddComment("Many to Many");
                            table.ManyToMany().ToList().ForEach(mtm =>
                            {
                                if (mtm.ForeignKeyColumn.PrimaryKeyOrder > 1)
                                {
                                    return;
                                }


                                var manyToManyTable = mtm.ForeignKeyColumn.Table;
                                var otherFk         = mtm.ForeignKeyColumn.Table.ForeignKeys.First(t => t.ForeignKeyColumn.PrimaryKeyOrder > 1);
                                var otherFkTable    = otherFk.PrimaryKeyColumn.Table;
                                var manyProp        = FindNavigation(entityClass, mtm);

                                // exclude if not being generated.
                                if (!TablesToGenerate.Contains(otherFk.PrimaryKeyColumn.Table))
                                {
                                    return;
                                }

                                var otherNamespace = TableNamespace(otherFkTable);
                                var otherClassName = TableClassName(otherFkTable);
                                var otherEntity    = GenerationContext.FindClass(otherClassName, otherNamespace);
                                var otherProp      = FindNavigation(otherEntity, otherFk);

                                var line = RawLineBuilder.Create();
                                line.Append($"HasMany(t => t.{manyProp.GetName()})");
                                line.Append($".WithMany(t => t.{otherProp.GetName()})");
                                line.Append($".Map(t => t.{ToTableFluent(manyToManyTable)}");
                                line.Append($".MapLeftKey(\"{mtm.ForeignKeyColumn.Name}\")");
                                line.Append($".MapRightKey(\"{otherFk.ForeignKeyColumn.Name}\"))");
                                constructor.Add(line);
                            });
                        });
                    });
                });
            });
        }
Example #11
0
        protected virtual void GenerateModel(ITable table)
        {
            if (!Options.GenerateModels)
            {
                return;
            }

            var tableNamespace     = TableNamespace(table);
            var modelNamespace     = ModelNamespace(table);
            var tableClassName     = TableClassName(table);
            var modelClassName     = ModelClassName(table);
            var tableClassFullName = TableClassFullName(table);
            var tableClass         = GenerationContext.FindClass(tableClassName, tableNamespace);
            var fileBuilder        = ResolveModelFileBuilder(table);

            fileBuilder.Namespace(modelNamespace, true, ns =>
            {
                ns.Class(modelClass =>
                {
                    // set basic info.
                    modelClass.Partial(true).Name(modelClassName);

                    if (Options.GenerateModelsInterfaces)
                    {
                        var modelInterfaceFullName = ModelInterfaceFullName(table);
                        modelClass.Inherits(modelInterfaceFullName);
                    }

                    Options?.ModelInheritances.ForEach(mi =>
                    {
                        modelClass.Inherits(ReplaceMetas(mi, table));
                    });

                    MethodBuilder from = null;
                    MethodBuilder to   = null;
                    if (Options.GenerateModelsFromTo)
                    {
                        modelClass.Method(m =>
                        {
                            m
                            .AccessModifier(AccessModifiers.Public)
                            .Virtual(true)
                            .ReturnType("void")
                            .Name("From")
                            .Parameter(p => p.Type(tableClassFullName).Name("entity"));
                            from = m;
                        });

                        modelClass.Method(m =>
                        {
                            m
                            .AccessModifier(AccessModifiers.Public)
                            .Virtual(true)
                            .ReturnType("void")
                            .Name("To")
                            .Parameter(p => p.Type(tableClassFullName).Name("entity"));
                            to = m;
                        });
                    }

                    // set properties.
                    table.Columns.ForEach(column =>
                    {
                        modelClass.Property(columnProperty =>
                        {
                            var typeName = GetColumnTypeName(column, ShouldGenerateModelPropertyAsNullable(column)); // Options.GenerateModelPropertyAsNullable);
                            columnProperty
                            .Virtual(true)
                            .Name(column.Name)
                            .Type(typeName)
                            .Meta(column);

                            if (Options.GenerateModelsFromTo)
                            {
                                from.RawLine($"{column.Name} = entity.{column.Name}");
                                bool isPropertyNullable = IsModelPropertyNullable(column); // column.IsNullable || ShouldGenerateModelPropertyAsNullable(column);// Options.GenerateModelPropertyAsNullable;
                                if (isPropertyNullable && !column.IsNullable)
                                {
                                    var matchingProp = tableClass.FindByMeta <PropertyBuilder>(column);
                                    var ternary      = TernaryBuilder
                                                       .Create()
                                                       .RawCondition(rc => rc.Condition($"{column.Name} != null"))
                                                       .True(RawInlineBuilder.Create($"entity.{column.Name} = ({matchingProp.GetTypeName()}){column.Name}"))
                                                       .False(RawInlineBuilder.Create($"entity.{column.Name} = default({matchingProp.GetTypeName()})"));

                                    to.RawLine($"entity.{column.Name} = {ternary.GenerateInline()}");
                                }
                                else
                                {
                                    to.RawLine($"entity.{column.Name} = {column.Name}");
                                }
                            }
                        });
                    });
                });
            });
        }
Example #12
0
        protected virtual void GenerateModelExtensions(ITable table)
        {
            if (!Options.GenerateModelExtensions)
            {
                return;
            }

            if (!Options.GenerateModelsInterfaces && !Options.GenerateModels)
            {
                throw new Exception("Impossible to generate model extensions because neither GenerateModels or GenerateModelsInterfaces is activated.");
            }

            // full paths to model or interface
            var modelFullClassName     = ModelClassFullName(table);
            var modelInterfaceFullName = ModelInterfaceFullName(table);

            // poco.
            var pocoFullInterfaceName = TableInterfaceFullName(table);
            var pocoFullClassName     = TableClassFullName(table);

            // poco type.
            var pocoClassName      = TableClassName(table);
            var pocoClassNamespace = TableNamespace(table);
            var pocoClass          = GenerationContext.FindClass(pocoClassName, pocoClassNamespace);

            var modelExtensionNamespaceName = ModelExtensionsNamespace(table);
            var modelExtensionClassName     = ModelExtensionsClassName(table);
            var fileBuilder = ResolveModelExtensionFileBuilder(table);

            fileBuilder.Namespace(modelExtensionNamespaceName, true, ns =>
            {
                ns.Class(c =>
                {
                    // set basic info.
                    c.Partial(true).Static(true).Name(modelExtensionClassName);

                    var finalEntityType = Options.GenerateInterfaces ? pocoFullInterfaceName : pocoFullClassName;
                    var finalModelType  = Options.GenerateModelsInterfaces ? modelInterfaceFullName : modelFullClassName;

                    c.Method(m =>
                    {
                        m
                        .AccessModifier(AccessModifiers.Public)
                        .IsStatic(true)
                        .Name("ToModel")
                        .ReturnType("void")
                        .Parameter(p => p.Name("source").Type($"this {finalEntityType}"))
                        .Parameter(p => p.Name("model").Type(finalModelType));

                        table.Columns.ForEach(column =>
                        {
                            m.RawLine($"model.{column.Name} = source.{column.Name}");
                        });
                    });

                    c.Method(m =>
                    {
                        m
                        .AccessModifier(AccessModifiers.Public)
                        .IsStatic(true)
                        .Name("FromModel")
                        .ReturnType("void")
                        .Parameter(p => p.Name("model").Type($"this {finalModelType}"))
                        .Parameter(p => p.Name("destination").Type(finalEntityType))
                        .Parameter(p => p.Name("ignorePrimaryKey").Type("bool").DefaultValue("true"))
                        ;

                        table.Columns.ForEach(column =>
                        {
                            var rawLine             = "";
                            bool isPropertyNullable = IsModelPropertyNullable(column); // column.IsNullable || ShouldGenerateModelPropertyAsNullable(column);
                            if (isPropertyNullable && !column.IsNullable)
                            {
                                var matchingProp = pocoClass.FindByMeta <PropertyBuilder>(column);
                                var ternary      = TernaryBuilder
                                                   .Create()
                                                   .RawCondition(rc => rc.Condition($"model.{column.Name} != null"))
                                                   .True(RawInlineBuilder.Create(
                                                             $"destination.{column.Name} = ({matchingProp.GetTypeName()})model.{column.Name}"))
                                                   .False(RawInlineBuilder.Create(
                                                              $"destination.{column.Name} = default({matchingProp.GetTypeName()})"));

                                rawLine = $"destination.{column.Name} = {ternary.GenerateInline()}";
                            }
                            else
                            {
                                rawLine = $"destination.{column.Name} = model.{column.Name}";
                            }

                            if (column.IsPrimaryKey)
                            {
                                m.Add(IfBuilder.Create().RawCondition(rc => rc.Condition($"ignorePrimaryKey != true")).Add(RawLineBuilder.Create(rawLine)));
                            }
                            else
                            {
                                m.RawLine(rawLine);
                            }
                        });
                    });
                });
            });
        }