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