private void GenerateForeignKeyAttribute(INavigation navigation)
        {
            if (navigation.IsOnDependent)
            {
                if (navigation.ForeignKey.PrincipalKey.IsPrimaryKey())
                {
                    // TODO: Resolve TransformNavPropertyName() method
                    NavEntityPropertyInfo navEntityPropertyInfo = ResolvingNamesService.ResolvingName(navigation);

                    var foreignKeyAttribute = new AttributeWriter(nameof(ForeignKeyAttribute));

                    if (navigation.ForeignKey.Properties.Count > 1)
                    {
                        foreignKeyAttribute.AddParameter(
                            CSharpHelper.Literal(
                                string.Join(",", navigation.ForeignKey.Properties.Select(p => EntityTypeTransformationService.TransformNavPropertyName(navEntityPropertyInfo.FieldName, navEntityPropertyInfo.ForeginEntityName, navEntityPropertyInfo.EntityName, p.Name, p.ClrType.Name, navEntityPropertyInfo.PropertyIsNullable)))));
                    }
                    else
                    {
                        foreignKeyAttribute.AddParameter($"nameof({EntityTypeTransformationService.TransformNavPropertyName(navEntityPropertyInfo.FieldName, navEntityPropertyInfo.ForeginEntityName, navEntityPropertyInfo.EntityName, navigation.ForeignKey.Properties.First().Name, navigation.ForeignKey.Properties.First().ClrType.Name, navEntityPropertyInfo.PropertyIsNullable)})");
                    }

                    NavPropertyAnnotations.Add(new Dictionary <string, object>
                    {
                        { "nav-property-annotation", foreignKeyAttribute }
                    });
                }
            }
        }
        private void GenerateInversePropertyAttribute(INavigation navigation)
        {
            if (navigation.ForeignKey.PrincipalKey.IsPrimaryKey())
            {
                var inverseNavigation = navigation.Inverse;

                if (inverseNavigation != null)
                {
                    // TODO: Resolve TransformNavPropertyName() method
                    NavEntityPropertyInfo navEntityPropertyInfo = ResolvingNamesService.ResolvingName(navigation);

                    var foreignKeyAttribute = new AttributeWriter(nameof(ForeignKeyAttribute));

                    var inversePropertyAttribute = new AttributeWriter(nameof(InversePropertyAttribute));

                    var propertyName = EntityTypeTransformationService.TransformNavPropertyName(navEntityPropertyInfo.FieldName, navEntityPropertyInfo.ForeginEntityName, navEntityPropertyInfo.EntityName, inverseNavigation.Name, navigation.DeclaringType.Name, navEntityPropertyInfo.PropertyIsNullable);
                    inversePropertyAttribute.AddParameter(
                        !navigation.DeclaringEntityType.GetPropertiesAndNavigations().Any(
                            m => m.Name == inverseNavigation.DeclaringEntityType.Name ||
                            EntityTypeTransformationService.TransformNavPropertyName(navEntityPropertyInfo.FieldName, navEntityPropertyInfo.ForeginEntityName, navEntityPropertyInfo.EntityName, m.Name, navigation.TargetEntityType.Name, navEntityPropertyInfo.PropertyIsNullable)
                            == EntityTypeTransformationService.TransformNavPropertyName(navEntityPropertyInfo.FieldName, navEntityPropertyInfo.ForeginEntityName, navEntityPropertyInfo.EntityName, inverseNavigation.DeclaringEntityType.Name, navigation.TargetEntityType.Name, navEntityPropertyInfo.PropertyIsNullable))
                            ? $"nameof({EntityTypeTransformationService.TransformTypeEntityName(inverseNavigation.DeclaringType.Name)}.{propertyName})"
                            : CSharpHelper.Literal(propertyName));

                    NavPropertyAnnotations.Add(new Dictionary <string, object>
                    {
                        { "nav-property-annotation", inversePropertyAttribute }
                    });
                }
            }
        }
        /// <summary>
        /// Generate entity type constructor.
        /// </summary>
        /// <param name="entityType">Represents an entity type in an <see cref="T:Microsoft.EntityFrameworkCore.Metadata.IModel" />.</param>
        protected override void GenerateConstructor(IEntityType entityType)
        {
            Check.NotNull(entityType, nameof(entityType));

            var collectionNavigations = entityType.GetScaffoldNavigations(_options.Value)
                                        .Where(n => n.IsCollection).ToList();

            if (collectionNavigations.Count > 0)
            {
                var lines = new List <Dictionary <string, object> >();

                foreach (var navigation in collectionNavigations)
                {
                    lines.Add(new Dictionary <string, object>
                    {
                        { "property-name", navigation.Name },
                        { "property-type", navigation.TargetEntityType.Name }
                    });
                }

                var transformedLines = EntityTypeTransformationService.TransformConstructor(entityType.Name, lines);

                TemplateData.Add("lines", transformedLines);
            }
        }
        public override ScaffoldedModel GenerateModel(IModel model,
                                                      string @namespace,
                                                      string contextDir,
                                                      string contextName,
                                                      string connectionString,
                                                      ModelCodeGenerationOptions options)
        {
            EntityTypeConfigurationTemplateService.RegisterPartialTemplates();

            var resultingFiles = base.GenerateModel(model, @namespace, contextDir, contextName, connectionString, options);

            string generatedCode;

            if (!(CSharpEntityTypeConfigurationGenerator is NullCSharpEntityTypeConfigurationGenerator))
            {
                foreach (var entityType in model.GetEntityTypes())
                {
                    generatedCode = CSharpEntityTypeConfigurationGenerator.WriteCode(entityType, @namespace, options.UseDataAnnotations);

                    var transformedFileName   = EntityTypeTransformationService.TransformEntityTypeConfigurationFileName(entityType.DisplayName(), HandlebarsScaffoldingOptions.EntityTypeConfigurationFileNameSuffix);
                    var entityTypeCfgFileName = transformedFileName + FileExtension;
                    resultingFiles.AdditionalFiles.Add(new ScaffoldedFile {
                        Path = Path.Combine(contextDir, contextName + HandlebarsScaffoldingOptions.EntityTypeConfigurationDirSuffix, entityTypeCfgFileName), Code = generatedCode
                    });
                }
            }

            return(resultingFiles);
        }
示例#5
0
        /// <summary>
        /// Generate entity type navigation properties.
        /// </summary>
        /// <param name="entityType">Represents an entity type in an <see cref="T:Microsoft.EntityFrameworkCore.Metadata.IModel" />.</param>
        protected override void GenerateNavigationProperties(IEntityType entityType)
        {
            Check.NotNull(entityType, nameof(entityType));

            var sortedNavigations = entityType.GetNavigations()
                                    .OrderBy(n => n.IsOnDependent ? 0 : 1)
                                    .ThenBy(n => n.IsCollection ? 1 : 0);

            if (sortedNavigations.Any())
            {
                var navProperties = new List <Dictionary <string, object> >();

                foreach (var navigation in sortedNavigations)
                {
                    // TODO: Resolve TransformNavPropertyName() method
                    NavEntityPropertyInfo navEntityPropertyInfo = ResolvingNamesService.ResolvingName(navigation);
                    navProperties.Add(new Dictionary <string, object>
                    {
                        { "foregin-entity-name", navEntityPropertyInfo.ForeginEntityName },
                        { "field-name", navEntityPropertyInfo.FieldName },
                        { "nav-property-collection", navigation.IsCollection },
                        { "nav-property-type", navigation.TargetEntityType.Name },
                        { "nav-property-name", TypeScriptHelper.ToCamelCase(navigation.Name) },
                        { "nav-property-annotations", new List <Dictionary <string, object> >() },
                        { "nullable-reference-types", _options?.Value?.EnableNullableReferenceTypes == true }
                    });
                }

                var transformedNavProperties = EntityTypeTransformationService.TransformNavigationProperties(entityType.Name, navProperties);

                TemplateData.Add("nav-properties", transformedNavProperties);
            }
        }
        private void GenerateRelationship(IForeignKey foreignKey, bool useDataAnnotations, IndentedStringBuilder sb)
        {
            var canUseDataAnnotations = true;
            var annotations           = AnnotationCodeGenerator
                                        .FilterIgnoredAnnotations(foreignKey.GetAnnotations())
                                        .ToDictionary(a => a.Name, a => a);

            AnnotationCodeGenerator.RemoveAnnotationsHandledByConventions(foreignKey, annotations);

            var lines = new List <string>
            {
                $".{nameof(EntityTypeBuilder.HasOne)}("
                + (foreignKey.DependentToPrincipal != null ? $"d => d.{EntityTypeTransformationService.TransformNavPropertyName(foreignKey.DependentToPrincipal?.Name, foreignKey.PrincipalToDependent?.DeclaringType.Name)}" : null)
                + ")",
                $".{(foreignKey.IsUnique ? nameof(ReferenceNavigationBuilder.WithOne) : nameof(ReferenceNavigationBuilder.WithMany))}"
                + "("
                + (foreignKey.PrincipalToDependent != null ? $"p => p.{EntityTypeTransformationService.TransformNavPropertyName(foreignKey.PrincipalToDependent?.Name, foreignKey.DependentToPrincipal?.DeclaringType.Name)}" : null)
                + ")"
            };

            if (!foreignKey.PrincipalKey.IsPrimaryKey())
            {
                canUseDataAnnotations = false;
                lines.Add(
                    $".{nameof(ReferenceReferenceBuilder.HasPrincipalKey)}"
                    + (foreignKey.IsUnique ? $"<{EntityTypeTransformationService.TransformPropertyName(((ITypeBase)foreignKey.PrincipalEntityType).DisplayName(), "")}>" : "")
                    + $"(p => {GenerateLambdaToKey(foreignKey.PrincipalKey.Properties, "p", EntityTypeTransformationService.TransformNavPropertyName)})");
            }

            lines.Add(
                $".{nameof(ReferenceReferenceBuilder.HasForeignKey)}"
                + (foreignKey.IsUnique ? $"<{GetEntityTypeName(foreignKey.PrincipalEntityType, EntityTypeTransformationService.TransformTypeEntityName(((ITypeBase)foreignKey.DeclaringEntityType).DisplayName()))}>" : "")
                + $"(d => {GenerateLambdaToKey(foreignKey.Properties, "d", EntityTypeTransformationService.TransformPropertyName)})");

            var defaultOnDeleteAction = foreignKey.IsRequired
                ? DeleteBehavior.Cascade
                : DeleteBehavior.ClientSetNull;

            if (foreignKey.DeleteBehavior != defaultOnDeleteAction)
            {
                canUseDataAnnotations = false;
                lines.Add(
                    $".{nameof(ReferenceReferenceBuilder.OnDelete)}({CSharpHelper.Literal(foreignKey.DeleteBehavior)})");
            }

            if (!string.IsNullOrEmpty((string)foreignKey[RelationalAnnotationNames.Name]))
            {
                canUseDataAnnotations = false;
            }

            lines.AddRange(
                AnnotationCodeGenerator.GenerateFluentApiCalls(foreignKey, annotations).Select(m => CSharpHelper.Fragment(m))
                .Concat(GenerateAnnotations(annotations.Values)));

            if (!useDataAnnotations ||
                !canUseDataAnnotations)
            {
                AppendMultiLineFluentApi(foreignKey.DeclaringEntityType, lines, sb);
            }
        }
示例#7
0
 private void AllGenerateEntityTypeConfigurations(IModel model, IndentedStringBuilder sb)
 {
     foreach (var entityType in model.GetEntityTypes())
     {
         var entityTypeCfgName = EntityTypeTransformationService.TransformEntityTypeConfigurationName(entityType.Name, HandlebarsScaffoldingOptions.EntityTypeConfigurationFileNameSuffix);
         sb.AppendLine($"modelBuilder.ApplyConfiguration(new {entityTypeCfgName}());");
     }
 }
        /// <summary>
        /// Generate entity type navigation properties.
        /// </summary>
        /// <param name="entityType">Represents an entity type in an <see cref="T:Microsoft.EntityFrameworkCore.Metadata.IModel" />.</param>
        protected override void GenerateNavigationProperties(IEntityType entityType)
        {
            Check.NotNull(entityType, nameof(entityType));

            var sortedNavigations = entityType.GetScaffoldNavigations(_options.Value)
                                    .OrderBy(n => n.IsOnDependent ? 0 : 1)
                                    .ThenBy(n => n.IsCollection ? 1 : 0);

            if (sortedNavigations.Any())
            {
                var navProperties = new List <Dictionary <string, object> >();



                foreach (var navigation in sortedNavigations)
                {
                    NavPropertyAnnotations = new List <Dictionary <string, object> >();

                    // TODO: Resolve TransformNavPropertyName() method
                    NavEntityPropertyInfo navEntityPropertyInfo = ResolvingNamesService.ResolvingName(navigation);

                    if (UseDataAnnotations)
                    {
                        GenerateNavigationDataAnnotations(navigation);
                    }

                    var propertyIsNullable = !navigation.IsCollection && (
                        navigation.IsOnDependent
                        ? !navigation.ForeignKey.IsRequired
                        : !navigation.ForeignKey.IsRequiredDependent
                        );
                    var navPropertyType = navigation.TargetEntityType.Name;
                    if (_options?.Value?.EnableNullableReferenceTypes == true &&
                        !navPropertyType.EndsWith("?") &&
                        propertyIsNullable)
                    {
                        navPropertyType += "?";
                    }

                    navProperties.Add(new Dictionary <string, object>
                    {
                        { "foregin-entity-name", navEntityPropertyInfo.ForeginEntityName },
                        { "field-name", navEntityPropertyInfo.FieldName },
                        { "nav-property-collection", navigation.IsCollection },
                        { "nav-property-type", navPropertyType },
                        { "nav-property-name", navigation.Name },
                        { "nav-property-annotations", NavPropertyAnnotations },
                        { "nav-property-isnullable", propertyIsNullable },
                        { "nullable-reference-types", _options?.Value?.EnableNullableReferenceTypes == true }
                    });
                }

                var transformedNavProperties = EntityTypeTransformationService.TransformNavigationProperties(entityType.Name, navProperties);

                TemplateData.Add("nav-properties", transformedNavProperties);
            }
        }
示例#9
0
        /// <summary>
        /// Generate entity type class.
        /// </summary>
        /// <param name="entityType">Represents an entity type in an <see cref="T:Microsoft.EntityFrameworkCore.Metadata.IModel" />.</param>
        protected override void GenerateClass(IEntityType entityType)
        {
            Check.NotNull(entityType, nameof(entityType));

            var transformedEntityName = EntityTypeTransformationService.TransformTypeEntityName(entityType.Name);

            TemplateData.Add("comment", entityType.GetComment());
            TemplateData.Add("class", transformedEntityName);

            GenerateConstructor(entityType);
            GenerateProperties(entityType);
            GenerateNavigationProperties(entityType);
        }
        private void InitializeEntityTypeBuilder(IEntityType entityType, IndentedStringBuilder sb)
        {
            if (!_entityTypeBuilderInitialized)
            {
                var transformedEntityName = EntityTypeTransformationService.TransformEntityName(entityType.Name);

                sb.AppendLine();
                sb.AppendLine($"modelBuilder.Entity<{transformedEntityName}>({EntityLambdaIdentifier} =>");
                sb.Append("{");
            }

            _entityTypeBuilderInitialized = true;
        }
示例#11
0
        private string GenerateLambdaToKey(
            IReadOnlyList <IProperty> properties,
            string lambdaIdentifier)
        {
            if (properties.Count <= 0)
            {
                return("");
            }

            return(properties.Count == 1
                ? $"{lambdaIdentifier}.{EntityTypeTransformationService.TransformPropertyName(properties[0].Name)}"
                : $"new {{ {string.Join(", ", properties.Select(p => lambdaIdentifier + "." + EntityTypeTransformationService.TransformPropertyName(p.Name)))} }}");
        }
        private void GenerateDbSets(IModel model)
        {
            var dbSets = new List <Dictionary <string, object> >();

            foreach (var entityType in model.GetScaffoldEntityTypes(_options.Value))
            {
                var transformedEntityName = EntityTypeTransformationService.TransformEntityName(entityType.Name);
                dbSets.Add(new Dictionary <string, object>
                {
                    { "set-property-type", transformedEntityName },
                    { "set-property-name", entityType.GetDbSetName() },
                });
            }

            TemplateData.Add("dbsets", dbSets);
        }
        protected override void GenerateProperties(IEntityType entityType)
        {
            var properties = new List <Dictionary <string, object> >();

#pragma warning disable EF1001 // Internal EF Core API usage.
            foreach (var property in entityType.GetProperties().OrderBy(p => p.GetColumnOrdinal()))
#pragma warning restore EF1001 // Internal EF Core API usage.
            {
                PropertyAnnotationsData = new List <Dictionary <string, object> >();

                if (UseDataAnnotations)
                {
                    GeneratePropertyDataAnnotations(property);
                }

                var propertyType = CSharpHelper.Reference(property.ClrType);
                if (_options?.Value?.EnableNullableReferenceTypes == true &&
                    property.IsNullable &&
                    !propertyType.EndsWith("?"))
                {
                    propertyType += "?";
                }
                properties.Add(new Dictionary <string, object>
                {
                    { "property-type", propertyType },
                    { "property-name", property.Name },
                    { "property-annotations", PropertyAnnotationsData },
                    { "property-comment", property.GetComment() },
                    { "property-isnullable", property.IsNullable },
                    { "nullable-reference-types", _options?.Value?.EnableNullableReferenceTypes == true },

                    // Add new item to template data
                    { "property-isprimarykey", property.IsPrimaryKey() }
                });
            }

            var transformedProperties = EntityTypeTransformationService.TransformProperties(properties);

            // Add to transformed properties
            for (int i = 0; i < transformedProperties.Count; i++)
            {
                transformedProperties[i].Add("property-isprimarykey", properties[i]["property-isprimarykey"]);
            }

            TemplateData.Add("properties", transformedProperties);
        }
        private void GenerateDbSets(IModel model)
        {
            var dbSets = new List <Dictionary <string, object> >();

            foreach (var entityType in model.GetScaffoldEntityTypes(_options.Value))
            {
                var transformedEntityTypeName = GetEntityTypeName(
                    entityType, EntityTypeTransformationService.TransformTypeEntityName(entityType.Name));
                dbSets.Add(new Dictionary <string, object>
                {
                    { "set-property-type", transformedEntityTypeName },
                    { "set-property-name", entityType.GetDbSetName() },
                    { "nullable-reference-types", _options?.Value?.EnableNullableReferenceTypes == true }
                });
            }

            TemplateData.Add("dbsets", dbSets);
        }
        /// <summary>
        /// Generate entity type class.
        /// </summary>
        /// <param name="entityType">Represents an entity type in an <see cref="T:Microsoft.EntityFrameworkCore.Metadata.IModel" />.</param>
        protected override void GenerateClass(IEntityType entityType)
        {
            Check.NotNull(entityType, nameof(entityType));

            if (UseDataAnnotations)
            {
                GenerateEntityTypeDataAnnotations(entityType);
            }

            var transformedEntityName = EntityTypeTransformationService.TransformTypeEntityName(entityType.Name);

            if (_options?.Value?.GenerateComments == true)
            {
                TemplateData.Add("comment", GenerateComment(entityType.GetComment(), 1));
            }
            TemplateData.Add("class", transformedEntityName);

            GenerateConstructor(entityType);
            GenerateProperties(entityType);
            GenerateNavigationProperties(entityType);
        }
示例#16
0
        /// <summary>
        /// Generate entity type properties.
        /// </summary>
        /// <param name="entityType">Represents an entity type in an <see cref="T:Microsoft.EntityFrameworkCore.Metadata.IModel" />.</param>
        protected override void GenerateProperties(IEntityType entityType)
        {
            Check.NotNull(entityType, nameof(entityType));

            var properties = new List <Dictionary <string, object> >();

            foreach (var property in entityType.GetProperties().OrderBy(p => p.GetColumnOrdinal()))
            {
                properties.Add(new Dictionary <string, object>
                {
                    { "property-type", TypeScriptHelper.TypeName(property.ClrType) },
                    { "property-name", TypeScriptHelper.ToCamelCase(property.Name) },
                    { "property-annotations", new List <Dictionary <string, object> >() },
                    { "property-comment", property.GetComment() },
                    { "property-isnullable", property.IsNullable },
                    { "nullable-reference-types", _options?.Value?.EnableNullableReferenceTypes == true }
                });
            }

            var transformedProperties = EntityTypeTransformationService.TransformProperties(entityType.Name, properties);

            TemplateData.Add("properties", transformedProperties);
        }
        /// <summary>
        /// Generate entity type properties.
        /// </summary>
        /// <param name="entityType">Represents an entity type in an <see cref="T:Microsoft.EntityFrameworkCore.Metadata.IModel" />.</param>
        protected override void GenerateProperties(IEntityType entityType)
        {
            Check.NotNull(entityType, nameof(entityType));

            var properties = new List <Dictionary <string, object> >();

            foreach (var property in entityType.GetProperties().OrderBy(p => p.GetColumnOrdinal()))
            {
                PropertyAnnotationsData = new List <Dictionary <string, object> >();

                if (UseDataAnnotations)
                {
                    GeneratePropertyDataAnnotations(property);
                }

                var propertyType = CSharpHelper.Reference(property.ClrType);
                if (_options?.Value?.EnableNullableReferenceTypes == true &&
                    property.IsNullable &&
                    !propertyType.EndsWith("?"))
                {
                    propertyType += "?";
                }
                properties.Add(new Dictionary <string, object>
                {
                    { "property-type", propertyType },
                    { "property-name", property.Name },
                    { "property-annotations", PropertyAnnotationsData },
                    { "property-comment", _options?.Value?.GenerateComments == true ? GenerateComment(property.GetComment(), 2) : null },
                    { "property-isnullable", property.IsNullable },
                    { "nullable-reference-types", _options?.Value?.EnableNullableReferenceTypes == true }
                });
            }

            var transformedProperties = EntityTypeTransformationService.TransformProperties(entityType.Name, properties);

            TemplateData.Add("properties", transformedProperties);
        }
示例#18
0
        /// <summary>Generates code for a model.</summary>
        /// <param name="model"> The model. </param>
        /// <param name="namespace"> The namespace. </param>
        /// <param name="contextDir"> The directory of the <see cref="T:Microsoft.EntityFrameworkCore.DbContext" />. </param>
        /// <param name="contextName"> The name of the <see cref="T:Microsoft.EntityFrameworkCore.DbContext" />. </param>
        /// <param name="connectionString"> The connection string. </param>
        /// <param name="options"> The options to use during generation. </param>
        /// <returns> The generated model. </returns>
        public override ScaffoldedModel GenerateModel(IModel model,
                                                      string @namespace,
                                                      string contextDir,
                                                      string contextName,
                                                      string connectionString,
                                                      ModelCodeGenerationOptions options)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }
            if (string.IsNullOrWhiteSpace(@namespace))
            {
                throw new ArgumentNullException(nameof(@namespace));
            }
            if (contextDir == null)
            {
                throw new ArgumentNullException(nameof(contextDir));
            }
            if (string.IsNullOrWhiteSpace(contextName))
            {
                throw new ArgumentNullException(nameof(contextName));
            }
            if (string.IsNullOrWhiteSpace(connectionString))
            {
                throw new ArgumentNullException(nameof(connectionString));
            }
            if (contextDir == null)
            {
                throw new ArgumentNullException(nameof(contextDir));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            // Register Hbs helpers and partial templates
            HandlebarsHelperService.RegisterHelpers();
            DbContextTemplateService.RegisterPartialTemplates();
            EntityTypeTemplateService.RegisterPartialTemplates();

            var resultingFiles = new ScaffoldedModel();

            string generatedCode;

            if (!(CSharpDbContextGenerator is NullCSharpDbContextGenerator))
            {
                generatedCode = CSharpDbContextGenerator.WriteCode(model, @namespace, contextName, connectionString, options.UseDataAnnotations, options.SuppressConnectionStringWarning);

                var dbContextFileName = contextName + FileExtension;
                resultingFiles.ContextFile = new ScaffoldedFile {
                    Path = Path.Combine(contextDir, dbContextFileName), Code = generatedCode
                };
            }

            if (!(CSharpEntityTypeGenerator is NullCSharpEntityTypeGenerator))
            {
                foreach (var entityType in model.GetEntityTypes())
                {
                    generatedCode = CSharpEntityTypeGenerator.WriteCode(entityType, @namespace, options.UseDataAnnotations);

                    var transformedFileName = EntityTypeTransformationService.TransformEntityFileName(entityType.DisplayName());
                    var entityTypeFileName  = transformedFileName + FileExtension;
                    resultingFiles.AdditionalFiles.Add(new ScaffoldedFile {
                        Path = entityTypeFileName, Code = generatedCode
                    });
                }
            }

            return(resultingFiles);
        }
        private void GenerateProperty(IProperty property, bool useDataAnnotations, IndentedStringBuilder sb)
        {
            var lines = new List <string>
            {
                $".{nameof(EntityTypeBuilder.Property)}(e => e.{EntityTypeTransformationService.TransformPropertyName(property.Name, property.DeclaringType.Name)})"
            };

            var annotations = AnnotationCodeGenerator
                              .FilterIgnoredAnnotations(property.GetAnnotations())
                              .ToDictionary(a => a.Name, a => a);

            AnnotationCodeGenerator.RemoveAnnotationsHandledByConventions(property, annotations);
            annotations.Remove(ScaffoldingAnnotationNames.ColumnOrdinal);

            if (useDataAnnotations)
            {
                // Strip out any annotations handled as attributes - these are already handled when generating
                // the entity's properties
                // Only relational ones need to be removed here. Core ones are already removed by FilterIgnoredAnnotations
                annotations.Remove(RelationalAnnotationNames.ColumnName);
                annotations.Remove(RelationalAnnotationNames.ColumnType);

                _ = AnnotationCodeGenerator.GenerateDataAnnotationAttributes(property, annotations);
            }
            else
            {
                if (!property.IsNullable &&
                    property.ClrType.IsNullableType() &&
                    !property.IsPrimaryKey())
                {
                    lines.Add($".{nameof(PropertyBuilder.IsRequired)}()");
                }

                var columnType = property.GetConfiguredColumnType();
                if (columnType != null)
                {
                    lines.Add(
                        $".{nameof(RelationalPropertyBuilderExtensions.HasColumnType)}({CSharpHelper.Literal(columnType)})");
                    annotations.Remove(RelationalAnnotationNames.ColumnType);
                }

                var maxLength = property.GetMaxLength();
                if (maxLength.HasValue)
                {
                    lines.Add(
                        $".{nameof(PropertyBuilder.HasMaxLength)}({CSharpHelper.Literal(maxLength.Value)})");
                }
            }

            var precision = property.GetPrecision();
            var scale     = property.GetScale();

            if (precision != null && scale != null && scale != 0)
            {
                lines.Add(
                    $".{nameof(PropertyBuilder.HasPrecision)}({CSharpHelper.Literal(precision.Value)}, {CSharpHelper.Literal(scale.Value)})");
            }
            else if (precision != null)
            {
                lines.Add(
                    $".{nameof(PropertyBuilder.HasPrecision)}({CSharpHelper.Literal(precision.Value)})");
            }

            if (property.IsUnicode() != null)
            {
                lines.Add(
                    $".{nameof(PropertyBuilder.IsUnicode)}({(property.IsUnicode() == false ? "false" : "")})");
            }

            var defaultValue = property.GetDefaultValue();

            if (defaultValue == DBNull.Value)
            {
                lines.Add($".{nameof(RelationalPropertyBuilderExtensions.HasDefaultValue)}()");
                annotations.Remove(RelationalAnnotationNames.DefaultValue);
            }
            else if (defaultValue != null)
            {
                lines.Add(
                    $".{nameof(RelationalPropertyBuilderExtensions.HasDefaultValue)}({CSharpHelper.UnknownLiteral(defaultValue)})");
                annotations.Remove(RelationalAnnotationNames.DefaultValue);
            }

            var valueGenerated = property.ValueGenerated;
            var isRowVersion   = false;

            if (((IConventionProperty)property).GetValueGeneratedConfigurationSource() is ConfigurationSource
                valueGeneratedConfigurationSource &&
                valueGeneratedConfigurationSource != ConfigurationSource.Convention &&
                ValueGenerationConvention.GetValueGenerated(property) != valueGenerated)
            {
                var methodName = valueGenerated switch
                {
                    ValueGenerated.OnAdd => nameof(PropertyBuilder.ValueGeneratedOnAdd),
                    ValueGenerated.OnAddOrUpdate => property.IsConcurrencyToken
                        ? nameof(PropertyBuilder.IsRowVersion)
                        : nameof(PropertyBuilder.ValueGeneratedOnAddOrUpdate),
                    ValueGenerated.OnUpdate => nameof(PropertyBuilder.ValueGeneratedOnUpdate),
                    ValueGenerated.Never => nameof(PropertyBuilder.ValueGeneratedNever),
                    _ => throw new InvalidOperationException(DesignStrings.UnhandledEnumValue($"{nameof(ValueGenerated)}.{valueGenerated}"))
                };

                lines.Add($".{methodName}()");
            }

            if (property.IsConcurrencyToken &&
                !isRowVersion)
            {
                lines.Add($".{nameof(PropertyBuilder.IsConcurrencyToken)}()");
            }

            lines.AddRange(
                AnnotationCodeGenerator.GenerateFluentApiCalls(property, annotations).Select(m => CSharpHelper.Fragment(m))
                .Concat(GenerateAnnotations(annotations.Values)));

            switch (lines.Count)
            {
            case 1:
                return;

            case 2:
                lines = new List <string> {
                    lines[0] + lines[1]
                };
                break;
            }

            AppendMultiLineFluentApi(property.DeclaringEntityType, lines, sb);
        }
示例#20
0
        private void GenerateRelationship(IForeignKey foreignKey, string dependentPropName, string principalPropName,
                                          bool useDataAnnotations, IndentedStringBuilder sb)
        {
            var canUseDataAnnotations = true;
            var annotations           = foreignKey.GetAnnotations().ToList();

            var lines = new List <string>
            {
                $".{nameof(EntityTypeBuilder.HasOne)}(d => d.{dependentPropName})",
                $".{(foreignKey.IsUnique ? nameof(ReferenceNavigationBuilder.WithOne) : nameof(ReferenceNavigationBuilder.WithMany))}"
                + $"(p => p.{principalPropName})"
            };

            if (!foreignKey.PrincipalKey.IsPrimaryKey())
            {
                canUseDataAnnotations = false;
                var principlePropDisplayName = EntityTypeTransformationService
                                               .TransformPropertyName(foreignKey.PrincipalEntityType.DisplayName());
                lines.Add(
                    $".{nameof(ReferenceReferenceBuilder.HasPrincipalKey)}"
                    + $"{(foreignKey.IsUnique ? $"<{principlePropDisplayName}>" : "")}"
                    + $"(p => {GenerateLambdaToKey(foreignKey.PrincipalKey.Properties, "p")})");
            }

            var dependentPropDisplayName = EntityTypeTransformationService
                                           .TransformPropertyName(foreignKey.DeclaringEntityType.DisplayName());

            lines.Add(
                $".{nameof(ReferenceReferenceBuilder.HasForeignKey)}"
                + $"{(foreignKey.IsUnique ? $"<{dependentPropDisplayName}>" : "")}"
                + $"(d => {GenerateLambdaToKey(foreignKey.Properties, "d")})");

            var defaultOnDeleteAction = foreignKey.IsRequired
                ? DeleteBehavior.Cascade
                : DeleteBehavior.ClientSetNull;

            if (foreignKey.DeleteBehavior != defaultOnDeleteAction)
            {
                canUseDataAnnotations = false;
                lines.Add(
                    $".{nameof(ReferenceReferenceBuilder.OnDelete)}" +
                    $"({CSharpHelper.Literal(foreignKey.DeleteBehavior)})");
            }

            if (!string.IsNullOrEmpty((string)foreignKey[RelationalAnnotationNames.Name]))
            {
                canUseDataAnnotations = false;
                lines.Add(
                    $".{nameof(RelationalReferenceReferenceBuilderExtensions.HasConstraintName)}" +
                    $"({CSharpHelper.Literal(foreignKey.Relational().Name)})");
                RemoveAnnotation(ref annotations, RelationalAnnotationNames.Name);
            }

            var annotationsToRemove = new List <IAnnotation>();

            foreach (var annotation in annotations)
            {
                if (CodeGenerator.IsHandledByConvention(foreignKey, annotation))
                {
                    annotationsToRemove.Add(annotation);
                }
                else
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    var line = CodeGenerator.GenerateFluentApi(foreignKey, annotation, Language);
#pragma warning restore CS0618 // Type or member is obsolete

                    if (line != null)
                    {
                        canUseDataAnnotations = false;
                        lines.Add(line);
                        annotationsToRemove.Add(annotation);
                    }
                }
            }

            lines.AddRange(GenerateAnnotations(annotations.Except(annotationsToRemove)));

            if (!useDataAnnotations ||
                !canUseDataAnnotations)
            {
                AppendMultiLineFluentApi(foreignKey.DeclaringEntityType, lines, sb);
            }
        }
示例#21
0
        private void GenerateEntityType(IEntityType entityType, bool useDataAnnotations,
                                        IndentedStringBuilder sb)
        {
            GenerateKey(entityType.FindPrimaryKey(), useDataAnnotations, sb);

            var annotations = entityType.GetAnnotations().ToList();

            RemoveAnnotation(ref annotations, RelationalAnnotationNames.TableName);
            RemoveAnnotation(ref annotations, RelationalAnnotationNames.Schema);
            RemoveAnnotation(ref annotations, ScaffoldingAnnotationNames.DbSetName);

            if (!useDataAnnotations)
            {
                GenerateTableName(entityType, sb);
            }

            var annotationsToRemove = new List <IAnnotation>();
            var lines = new List <string>();

            foreach (var annotation in annotations)
            {
                if (CodeGenerator.IsHandledByConvention(entityType, annotation))
                {
                    annotationsToRemove.Add(annotation);
                }
                else
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    var line = CodeGenerator.GenerateFluentApi(entityType, annotation, Language);
#pragma warning restore CS0618 // Type or member is obsolete

                    if (line != null)
                    {
                        lines.Add(line);
                        annotationsToRemove.Add(annotation);
                    }
                }
            }

            lines.AddRange(GenerateAnnotations(annotations.Except(annotationsToRemove)));

            AppendMultiLineFluentApi(entityType, lines, sb);

            foreach (var index in entityType.GetIndexes())
            {
                GenerateIndex(index, sb);
            }

            foreach (var property in entityType.GetProperties())
            {
                var transformedPropName = EntityTypeTransformationService.TransformPropertyName(property.Name);
                GenerateProperty(property, transformedPropName, useDataAnnotations, sb);
            }

            foreach (var foreignKey in entityType.GetForeignKeys())
            {
                var transformedDepPropName       = EntityTypeTransformationService.TransformPropertyName(foreignKey.DependentToPrincipal.Name);
                var transformedPrincipalPropName = EntityTypeTransformationService.TransformPropertyName(foreignKey.PrincipalToDependent.Name);
                GenerateRelationship(foreignKey, transformedDepPropName, transformedPrincipalPropName, useDataAnnotations, sb);
            }
        }
        private void GenerateRelationship(IForeignKey foreignKey, bool useDataAnnotations, IndentedStringBuilder sb)
        {
            var canUseDataAnnotations = true;
            var annotations           = foreignKey.GetAnnotations().ToList();

            var lines = new List <string>
            {
                $".{nameof(EntityTypeBuilder.HasOne)}(" + (foreignKey.DependentToPrincipal != null ? $"d => d.{EntityTypeTransformationService.TransformNavPropertyName(foreignKey.DependentToPrincipal?.Name, foreignKey.PrincipalToDependent?.DeclaringType.Name)}" : null) + ")",
                $".{(foreignKey.IsUnique ? nameof(ReferenceNavigationBuilder.WithOne) : nameof(ReferenceNavigationBuilder.WithMany))}"
                + $"(" + (foreignKey.PrincipalToDependent != null ? $"p => p.{EntityTypeTransformationService.TransformNavPropertyName(foreignKey.PrincipalToDependent?.Name, foreignKey.DependentToPrincipal?.DeclaringType.Name)}" : null) + ")"
            };

            if (!foreignKey.PrincipalKey.IsPrimaryKey())
            {
                canUseDataAnnotations = false;
                lines.Add(
                    $".{nameof(ReferenceReferenceBuilder.HasPrincipalKey)}"
                    + (foreignKey.IsUnique ? $"<{EntityTypeTransformationService.TransformPropertyName(((ITypeBase)foreignKey.PrincipalEntityType).DisplayName(), "")}>" : "")
                    + $"(p => {GenerateLambdaToKey(foreignKey.PrincipalKey.Properties, "p", EntityTypeTransformationService.TransformNavPropertyName)})");
            }

            lines.Add(
                $".{nameof(ReferenceReferenceBuilder.HasForeignKey)}"
                + (foreignKey.IsUnique ? $"<{GetEntityTypeName(foreignKey.PrincipalEntityType, EntityTypeTransformationService.TransformTypeEntityName(((ITypeBase)foreignKey.DeclaringEntityType).DisplayName()))}>" : "")
                + $"(d => {GenerateLambdaToKey(foreignKey.Properties, "d", EntityTypeTransformationService.TransformPropertyName)})");

            var defaultOnDeleteAction = foreignKey.IsRequired
                ? DeleteBehavior.Cascade
                : DeleteBehavior.ClientSetNull;

            if (foreignKey.DeleteBehavior != defaultOnDeleteAction)
            {
                canUseDataAnnotations = false;
                lines.Add(
                    $".{nameof(ReferenceReferenceBuilder.OnDelete)}" +
                    $"({CSharpHelper.Literal(foreignKey.DeleteBehavior)})");
            }

            if (!string.IsNullOrEmpty((string)foreignKey[RelationalAnnotationNames.Name]))
            {
                canUseDataAnnotations = false;
                lines.Add(
                    $".HasConstraintName" +
                    $"({CSharpHelper.Literal(foreignKey.GetConstraintName())})");
                RemoveAnnotation(ref annotations, RelationalAnnotationNames.Name);
            }

            var annotationsToRemove = new List <IAnnotation>();

            foreach (var annotation in annotations)
            {
                if (annotation.Value == null ||
                    AnnotationCodeGenerator.IsHandledByConvention(foreignKey, annotation))
                {
                    annotationsToRemove.Add(annotation);
                }
                else
                {
                    var methodCall = AnnotationCodeGenerator.GenerateFluentApi(foreignKey, annotation);
                    if (methodCall != null)
                    {
                        canUseDataAnnotations = false;
                        lines.Add(CSharpHelper.Fragment(methodCall));
                        annotationsToRemove.Add(annotation);
                    }
                }
            }

            lines.AddRange(GenerateAnnotations(annotations.Except(annotationsToRemove)));

            if (!useDataAnnotations ||
                !canUseDataAnnotations)
            {
                AppendMultiLineFluentApi(foreignKey.DeclaringEntityType, lines, sb);
            }
        }
        private void GenerateProperty(IProperty property, bool useDataAnnotations, IndentedStringBuilder sb)
        {
            var lines = new List <string>
            {
                $".{nameof(EntityTypeBuilder.Property)}(e => e.{EntityTypeTransformationService.TransformPropertyName(property.Name, property.DeclaringType.Name)})"
            };

            var annotations = property.GetAnnotations().ToList();

            RemoveAnnotation(ref annotations, RelationalAnnotationNames.ColumnName);
            RemoveAnnotation(ref annotations, RelationalAnnotationNames.ColumnType);
            RemoveAnnotation(ref annotations, CoreAnnotationNames.MaxLength);
            RemoveAnnotation(ref annotations, CoreAnnotationNames.TypeMapping);
            RemoveAnnotation(ref annotations, CoreAnnotationNames.Unicode);
            RemoveAnnotation(ref annotations, RelationalAnnotationNames.DefaultValue);
            RemoveAnnotation(ref annotations, RelationalAnnotationNames.DefaultValueSql);
            RemoveAnnotation(ref annotations, RelationalAnnotationNames.Comment);
            RemoveAnnotation(ref annotations, RelationalAnnotationNames.ComputedColumnSql);
            RemoveAnnotation(ref annotations, RelationalAnnotationNames.IsFixedLength);
            RemoveAnnotation(ref annotations, ScaffoldingAnnotationNames.ColumnOrdinal);

            if (!useDataAnnotations)
            {
                if (!property.IsNullable &&
                    property.ClrType.IsNullableType() &&
                    !property.IsPrimaryKey())
                {
                    lines.Add($".{nameof(PropertyBuilder.IsRequired)}()");
                }

                var columnName = property.GetColumnName();

                if (columnName != null &&
                    columnName != property.Name)
                {
                    lines.Add(
                        $".{nameof(RelationalPropertyBuilderExtensions.HasColumnName)}" +
                        $"({CSharpHelper.Literal(columnName)})");
                }

                var columnType = property.GetConfiguredColumnType();

                if (columnType != null)
                {
                    lines.Add(
                        $".{nameof(RelationalPropertyBuilderExtensions.HasColumnType)}" +
                        $"({CSharpHelper.Literal(columnType)})");
                }

                var maxLength = property.GetMaxLength();

                if (maxLength.HasValue)
                {
                    lines.Add(
                        $".{nameof(PropertyBuilder.HasMaxLength)}" +
                        $"({CSharpHelper.Literal(maxLength.Value)})");
                }
            }

            if (property.IsUnicode() != null)
            {
                lines.Add(
                    $".{nameof(PropertyBuilder.IsUnicode)}" +
                    $"({(property.IsUnicode() == false ? "false" : "")})");
            }

            if (property.IsFixedLength())
            {
                lines.Add(
                    $".{nameof(RelationalPropertyBuilderExtensions.IsFixedLength)}()");
            }

            if (property.GetDefaultValue() != null)
            {
                lines.Add(
                    $".{nameof(RelationalPropertyBuilderExtensions.HasDefaultValue)}" +
                    $"({CSharpHelper.UnknownLiteral(property.GetDefaultValue())})");
            }

            if (property.GetDefaultValueSql() != null)
            {
                lines.Add(
                    $".{nameof(RelationalPropertyBuilderExtensions.HasDefaultValueSql)}" +
                    $"({CSharpHelper.Literal(property.GetDefaultValueSql())})");
            }

            if (property.GetComment() != null)
            {
                lines.Add(
                    $".{nameof(RelationalPropertyBuilderExtensions.HasComment)}" +
                    $"({CSharpHelper.Literal(property.GetComment())})");
            }

            if (property.GetComputedColumnSql() != null)
            {
                lines.Add(
                    $".{nameof(RelationalPropertyBuilderExtensions.HasComputedColumnSql)}" +
                    $"({CSharpHelper.Literal(property.GetComputedColumnSql())})");
            }

            var valueGenerated = property.ValueGenerated;
            var isRowVersion   = false;

            if (((IConventionProperty)property).GetValueGeneratedConfigurationSource().HasValue &&
                RelationalValueGenerationConvention.GetValueGenerated(property) != valueGenerated)
            {
                string methodName;
                switch (valueGenerated)
                {
                case ValueGenerated.OnAdd:
                    methodName = nameof(PropertyBuilder.ValueGeneratedOnAdd);
                    break;

                case ValueGenerated.OnAddOrUpdate:
                    isRowVersion = property.IsConcurrencyToken;
                    methodName   = isRowVersion
                            ? nameof(PropertyBuilder.IsRowVersion)
                            : nameof(PropertyBuilder.ValueGeneratedOnAddOrUpdate);
                    break;

                case ValueGenerated.Never:
                    methodName = nameof(PropertyBuilder.ValueGeneratedNever);
                    break;

                default:
                    methodName = "";
                    break;
                }

                lines.Add($".{methodName}()");
            }

            if (property.IsConcurrencyToken &&
                !isRowVersion)
            {
                lines.Add($".{nameof(PropertyBuilder.IsConcurrencyToken)}()");
            }

            var annotationsToRemove = new List <IAnnotation>();

            foreach (var annotation in annotations)
            {
                if (annotation.Value == null ||
                    AnnotationCodeGenerator.IsHandledByConvention(property, annotation))
                {
                    annotationsToRemove.Add(annotation);
                }
                else
                {
                    var methodCall = AnnotationCodeGenerator.GenerateFluentApi(property, annotation);
                    if (methodCall != null)
                    {
                        lines.Add(CSharpHelper.Fragment(methodCall));
                        annotationsToRemove.Add(annotation);
                    }
                }
            }

            lines.AddRange(GenerateAnnotations(annotations.Except(annotationsToRemove)));

            switch (lines.Count)
            {
            case 1:
                return;

            case 2:
                lines = new List <string>
                {
                    lines[0] + lines[1]
                };
                break;
            }

            AppendMultiLineFluentApi(property.DeclaringEntityType, lines, sb);
        }
        /// <summary>
        /// <summary>Generates code for a model.</summary>
        /// </summary>
        /// <param name="model"> The model.</param>
        /// <param name="options"> The options to use during generation. </param>
        /// <returns> The generated model. </returns>
        public override ScaffoldedModel GenerateModel(IModel model, ModelCodeGenerationOptions options)
        {
            Check.NotNull(model, nameof(model));
            Check.NotNull(options, nameof(options));

            // Register Hbs helpers and partial templates
            HandlebarsHelperService.RegisterHelpers();
            HandlebarsBlockHelperService.RegisterBlockHelpers();
            DbContextTemplateService.RegisterPartialTemplates();
            EntityTypeTemplateService.RegisterPartialTemplates();

            var resultingFiles = new ScaffoldedModel();

            string generatedCode;

            if (!(CSharpDbContextGenerator is NullCSharpDbContextGenerator))
            {
                generatedCode = CSharpDbContextGenerator.WriteCode(
                    model,
                    options.ContextName,
                    options.ConnectionString,
                    options.ContextNamespace,
                    options.ModelNamespace,
                    options.UseDataAnnotations,
                    options.SuppressConnectionStringWarning,
                    options.SuppressOnConfiguring);

                var dbContextFileName = ContextTransformationService.TransformContextFileName(options.ContextName) + FileExtension;
                resultingFiles.ContextFile = new ScaffoldedFile
                {
                    Path = options.ContextDir != null
                        ? Path.Combine(options.ContextDir, dbContextFileName)
                        : dbContextFileName,
                    Code = generatedCode
                };
            }

            if (!(CSharpEntityTypeGenerator is NullCSharpEntityTypeGenerator))
            {
                foreach (var entityType in model.GetScaffoldEntityTypes(_options.Value))
                {
                    generatedCode = CSharpEntityTypeGenerator.WriteCode(
                        entityType,
                        options.ModelNamespace,
                        options.UseDataAnnotations);

                    var transformedFileName = EntityTypeTransformationService.TransformEntityFileName(entityType.DisplayName());
                    var entityTypeFileName  = _options?.Value?.EnableSchemaFolders == true
                        ? Path.Combine(CSharpHelper.Namespace(entityType.GetSchema()), transformedFileName + FileExtension)
                        : transformedFileName + FileExtension;

                    resultingFiles.AdditionalFiles.Add(
                        new ScaffoldedFile
                    {
                        Path = entityTypeFileName,
                        Code = generatedCode
                    });
                }
            }

            return(resultingFiles);
        }