private void GenerateEntityType(IEntityType entityType, bool useDataAnnotations, IndentedStringBuilder sb) { GenerateKey(entityType.FindPrimaryKey(), entityType, useDataAnnotations, sb); var annotations = AnnotationCodeGenerator .FilterIgnoredAnnotations(entityType.GetAnnotations()) .ToDictionary(a => a.Name, a => a); AnnotationCodeGenerator.RemoveAnnotationsHandledByConventions(entityType, annotations); annotations.Remove(RelationalAnnotationNames.TableName); annotations.Remove(RelationalAnnotationNames.Schema); annotations.Remove(RelationalAnnotationNames.ViewName); annotations.Remove(RelationalAnnotationNames.ViewSchema); annotations.Remove(ScaffoldingAnnotationNames.DbSetName); annotations.Remove(RelationalAnnotationNames.ViewDefinitionSql); if (useDataAnnotations) { // Strip out any annotations handled as attributes - these are already handled when generating // the entity's properties _ = AnnotationCodeGenerator.GenerateDataAnnotationAttributes(entityType, annotations); } if (!useDataAnnotations || entityType.GetViewName() != null) { GenerateTableName(entityType, sb); } var lines = new List <string>( AnnotationCodeGenerator.GenerateFluentApiCalls(entityType, annotations).Select(m => CSharpHelper.Fragment(m)) .Concat(GenerateAnnotations(annotations.Values))); AppendMultiLineFluentApi(entityType, lines, sb); foreach (var index in entityType.GetIndexes()) { // If there are annotations that cannot be represented using an IndexAttribute then use fluent API even // if useDataAnnotations is true. var indexAnnotations = AnnotationCodeGenerator .FilterIgnoredAnnotations(index.GetAnnotations()) .ToDictionary(a => a.Name, a => a); AnnotationCodeGenerator.RemoveAnnotationsHandledByConventions(index, indexAnnotations); if (!useDataAnnotations || indexAnnotations.Count > 0) { GenerateIndex(index, sb); } } foreach (var property in entityType.GetProperties()) { GenerateProperty(property, useDataAnnotations, sb); } foreach (var foreignKey in entityType.GetScaffoldForeignKeys(_options.Value)) { GenerateRelationship(foreignKey, useDataAnnotations, sb); } }
private void GenerateIndex(IIndex index, IndentedStringBuilder sb) { var annotations = AnnotationCodeGenerator .FilterIgnoredAnnotations(index.GetAnnotations()) .ToDictionary(a => a.Name, a => a); AnnotationCodeGenerator.RemoveAnnotationsHandledByConventions(index, annotations); var lines = new List <string> { $".{nameof(EntityTypeBuilder.HasIndex)}(e => {GenerateLambdaToKey(index.Properties, "e", EntityTypeTransformationService.TransformPropertyName)})" }; annotations.Remove(RelationalAnnotationNames.Name); if (index.IsUnique) { lines.Add($".{nameof(IndexBuilder.IsUnique)}()"); } lines.AddRange( AnnotationCodeGenerator.GenerateFluentApiCalls(index, annotations).Select(m => CSharpHelper.Fragment(m)) .Concat(GenerateAnnotations(annotations.Values))); AppendMultiLineFluentApi(index.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 = 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 GenerateKey(IKey key, IEntityType entityType, bool useDataAnnotations, IndentedStringBuilder sb) { if (key == null) { if (!useDataAnnotations) { var line = new List <string> { $".{nameof(EntityTypeBuilder.HasNoKey)}()" }; AppendMultiLineFluentApi(entityType, line, sb); } return; } var annotations = AnnotationCodeGenerator .FilterIgnoredAnnotations(key.GetAnnotations()) .ToDictionary(a => a.Name, a => a); AnnotationCodeGenerator.RemoveAnnotationsHandledByConventions(key, annotations); var explicitName = key.GetName() != key.GetDefaultName(); annotations.Remove(RelationalAnnotationNames.Name); if (key.Properties.Count == 1 && annotations.Count == 0) { if (key is Key concreteKey && key.Properties.SequenceEqual( KeyDiscoveryConvention.DiscoverKeyProperties( concreteKey.DeclaringEntityType, concreteKey.DeclaringEntityType.GetProperties()))) { return; } if (!explicitName && useDataAnnotations) { return; } } var lines = new List <string> { $".{nameof(EntityTypeBuilder.HasKey)}(e => {GenerateLambdaToKey(key.Properties, "e", EntityTypeTransformationService.TransformPropertyName)})" }; if (explicitName) { lines.Add( $".{nameof(RelationalKeyBuilderExtensions.HasName)}" + $"({CSharpHelper.Literal(key.GetName())})"); } lines.AddRange( AnnotationCodeGenerator.GenerateFluentApiCalls(key, annotations).Select(m => CSharpHelper.Fragment(m)) .Concat(GenerateAnnotations(annotations.Values))); AppendMultiLineFluentApi(key.DeclaringEntityType, lines, sb); }
/// <summary> /// Generate OnModelBuilding method. /// </summary> /// <param name="model">Metadata about the shape of entities, the relationships between them, and how they map to the database.</param> /// <param name="useDataAnnotations">Use fluent modeling API if false.</param> protected override void GenerateOnModelCreating([NotNull] IModel model, bool useDataAnnotations) { Check.NotNull(model, nameof(model)); var sb = new IndentedStringBuilder(); using (sb.Indent()) using (sb.Indent()) { sb.AppendLine("protected override void OnModelCreating(ModelBuilder modelBuilder)"); sb.Append("{"); var annotations = AnnotationCodeGenerator .FilterIgnoredAnnotations(model.GetAnnotations()) .ToDictionary(a => a.Name, a => a); AnnotationCodeGenerator.RemoveAnnotationsHandledByConventions(model, annotations); annotations.Remove(CoreAnnotationNames.ProductVersion); annotations.Remove(RelationalAnnotationNames.MaxIdentifierLength); annotations.Remove(ScaffoldingAnnotationNames.DatabaseName); annotations.Remove(ScaffoldingAnnotationNames.EntityTypeErrors); var lines = new List <string>(); lines.AddRange( AnnotationCodeGenerator.GenerateFluentApiCalls(model, annotations).Select(m => CSharpHelper.Fragment(m)) .Concat(GenerateAnnotations(annotations.Values))); if (lines.Count > 0) { using (sb.Indent()) { sb.AppendLine(); sb.Append("modelBuilder" + lines[0]); using (sb.Indent()) { foreach (var line in lines.Skip(1)) { sb.AppendLine(); sb.Append(line); } } sb.AppendLine(";"); } } using (sb.Indent()) { foreach (var entityType in model.GetScaffoldEntityTypes(_options.Value)) { _entityTypeBuilderInitialized = false; GenerateEntityType(entityType, useDataAnnotations, sb); if (_entityTypeBuilderInitialized) { sb.AppendLine("});"); } } foreach (var sequence in model.GetSequences()) { GenerateSequence(sequence, sb); } } sb.AppendLine(); using (sb.Indent()) { sb.AppendLine("OnModelCreatingPartial(modelBuilder);"); } sb.AppendLine("}"); sb.AppendLine(); sb.Append("partial void OnModelCreatingPartial(ModelBuilder modelBuilder);"); } var onModelCreating = sb.ToString(); TemplateData.Add("on-model-creating", onModelCreating); }
private void GenerateRelationship(IEntityType entityType, 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); // TODO: Resolve TransformNavPropertyName() method NavEntityPropertyInfo navEntityPropertyInfo = ResolvingNamesService.ResolvingName(entityType, foreignKey); var lines = new List <string> { $".{nameof(EntityTypeBuilder.HasOne)}(" + (foreignKey.DependentToPrincipal != null ? $"d => d.{EntityTypeTransformationService.TransformNavPropertyName(navEntityPropertyInfo.FieldName, navEntityPropertyInfo.ForeginEntityName, navEntityPropertyInfo.EntityName,foreignKey.DependentToPrincipal?.Name, foreignKey.PrincipalToDependent?.DeclaringType.Name, navEntityPropertyInfo.PropertyIsNullable)}" : null) + ")", $".{(foreignKey.IsUnique ? nameof(ReferenceNavigationBuilder.WithOne) : nameof(ReferenceNavigationBuilder.WithMany))}" + "(" + (foreignKey.PrincipalToDependent != null ? $"p => p.{EntityTypeTransformationService.TransformNavPropertyName(navEntityPropertyInfo.FieldName, navEntityPropertyInfo.ForeginEntityName, navEntityPropertyInfo.EntityName, foreignKey.PrincipalToDependent?.Name, foreignKey.DependentToPrincipal?.DeclaringType.Name, navEntityPropertyInfo.PropertyIsNullable)}" : null) + ")" }; if (!foreignKey.PrincipalKey.IsPrimaryKey()) { Func <string, string, string> tmpNameTransformFunction = (tmpName, tmpType) => { return(EntityTypeTransformationService.TransformNavPropertyName(navEntityPropertyInfo.FieldName, navEntityPropertyInfo.ForeginEntityName, navEntityPropertyInfo.EntityName, tmpName, tmpType, navEntityPropertyInfo.PropertyIsNullable)); }; canUseDataAnnotations = false; lines.Add( $".{nameof(ReferenceReferenceBuilder.HasPrincipalKey)}" + (foreignKey.IsUnique ? $"<{EntityTypeTransformationService.TransformPropertyName(((ITypeBase)foreignKey.PrincipalEntityType).DisplayName(), "")}>" : "") + $"(p => {GenerateLambdaToKey(foreignKey.PrincipalKey.Properties, "p", tmpNameTransformFunction)})"); } 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); } }