/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected virtual KeyBuilder VisitPrimaryKey([NotNull] EntityTypeBuilder builder, [NotNull] DatabaseTable table) { Check.NotNull(builder, nameof(builder)); Check.NotNull(table, nameof(table)); var primaryKey = table.PrimaryKey; if (primaryKey == null) { _reporter.WriteWarning(DesignStrings.MissingPrimaryKey(table.DisplayName())); return(null); } var unmappedColumns = primaryKey.Columns .Where(c => _unmappedColumns.Contains(c)) .Select(c => c.Name) .ToList(); if (unmappedColumns.Count > 0) { _reporter.WriteWarning( DesignStrings.PrimaryKeyErrorPropertyNotFound( table.DisplayName(), string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, unmappedColumns))); return(null); } var keyBuilder = builder.HasKey(primaryKey.Columns.Select(GetPropertyName).ToArray()); if (primaryKey.Columns.Count == 1 && primaryKey.Columns[0].ValueGenerated == null && primaryKey.Columns[0].DefaultValueSql == null) { var property = builder.Metadata.FindProperty(GetPropertyName(primaryKey.Columns[0]))?.AsProperty(); if (property != null) { var dummyLogger = new DiagnosticsLogger <DbLoggerCategory.Model>( new ScopedLoggerFactory(new LoggerFactory(), dispose: true), new LoggingOptions(), new DiagnosticListener("")); var conventionalValueGenerated = new RelationalValueGeneratorConvention(dummyLogger).GetValueGenerated(property); if (conventionalValueGenerated == ValueGenerated.OnAdd) { property.ValueGenerated = ValueGenerated.Never; } } } if (!string.IsNullOrEmpty(primaryKey.Name) && primaryKey.Name != ConstraintNamer.GetDefaultName(keyBuilder.Metadata)) { keyBuilder.HasName(primaryKey.Name); } keyBuilder.Metadata.AddAnnotations(primaryKey.GetAnnotations()); return(keyBuilder); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected virtual IndexBuilder VisitUniqueConstraint([NotNull] EntityTypeBuilder builder, [NotNull] DatabaseUniqueConstraint uniqueConstraint) { Check.NotNull(builder, nameof(builder)); Check.NotNull(uniqueConstraint, nameof(uniqueConstraint)); var unmappedColumns = uniqueConstraint.Columns .Where(c => _unmappedColumns.Contains(c)) .Select(c => c.Name) .ToList(); if (unmappedColumns.Count > 0) { _reporter.WriteWarning( DesignStrings.UnableToScaffoldIndexMissingProperty( uniqueConstraint.Name, string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, unmappedColumns))); return(null); } var propertyNames = uniqueConstraint.Columns.Select(GetPropertyName).ToArray(); var indexBuilder = builder.HasIndex(propertyNames).IsUnique(); if (!string.IsNullOrEmpty(uniqueConstraint.Name) && uniqueConstraint.Name != ConstraintNamer.GetDefaultName(indexBuilder.Metadata)) { indexBuilder.HasName(uniqueConstraint.Name); } indexBuilder.Metadata.AddAnnotations(uniqueConstraint.GetAnnotations()); return(indexBuilder); }
private void NameConstraintsCalled(object sender, EventArgs e) { var dte = (DTE)GetService(typeof(DTE)); if (null == dte || dte.ActiveDocument == null) { return; } var doc = dte.ActiveDocument.Object("TextDocument") as TextDocument; if (null == doc) { return; } var ep = doc.StartPoint.CreateEditPoint(); ep.EndOfDocument(); var length = ep.AbsoluteCharOffset; ep.StartOfDocument(); var originalText = ep.GetText(length); var namer = new ConstraintNamer(originalText); var modifiedText = namer.Go(); if (originalText != modifiedText) { ep.Delete(length); ep.Insert(modifiedText); } }
private static string Uniquify <T>(string baseIdentifier, string prefix, Dictionary <string, T> existingIdentifiers, int maxLength) { if (!string.IsNullOrEmpty(prefix) && !baseIdentifier.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { baseIdentifier = prefix + "_" + baseIdentifier; } var finalIdentifier = ConstraintNamer.Truncate(baseIdentifier, null, maxLength); var suffix = 1; while (existingIdentifiers.ContainsKey(finalIdentifier)) { finalIdentifier = ConstraintNamer.Truncate(baseIdentifier, suffix++, maxLength); } return(finalIdentifier); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected virtual IndexBuilder VisitIndex(EntityTypeBuilder builder, DatabaseIndex index) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (index == null) { throw new ArgumentNullException(nameof(index)); } var unmappedColumns = index.Columns .Where(c => _unmappedColumns.Contains(c)) .Select(c => c.Name) .ToList(); if (unmappedColumns.Any()) { _reporter.WriteWarning( DesignStrings.UnableToScaffoldIndexMissingProperty( index.Name, string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, unmappedColumns))); return(null); } var propertyNames = index.Columns.Select(GetPropertyName).ToArray(); var indexBuilder = builder.HasIndex(propertyNames) .IsUnique(index.IsUnique); if (index.Filter != null) { indexBuilder.HasFilter(index.Filter); } if (!string.IsNullOrEmpty(index.Name) && index.Name != ConstraintNamer.GetDefaultName(indexBuilder.Metadata)) { indexBuilder.HasName(index.Name); } indexBuilder.Metadata.AddAnnotations(index.GetAnnotations()); return(indexBuilder); }
private void GenerateKeyAttribute(IProperty property) { var key = property.AsProperty().PrimaryKey; if (key?.Properties.Count == 1) { if (key is Key concreteKey && key.Properties.SequenceEqual(new KeyDiscoveryConvention(null).DiscoverKeyProperties(concreteKey.DeclaringEntityType, concreteKey.DeclaringEntityType.GetProperties().ToList()))) { return; } if (key.Relational().Name != ConstraintNamer.GetDefaultName(key)) { return; } _sb.AppendLine(new AttributeWriter(nameof(KeyAttribute))); } }
private void NameConstraintsCalled(object sender, EventArgs e) { try { CallWrapper(); var dte = (DTE)GetService(typeof(DTE)); if (null == dte || dte.ActiveDocument == null) { return; } var doc = dte.ActiveDocument.Object("TextDocument") as TextDocument; if (null == doc) { return; } var ep = doc.StartPoint.CreateEditPoint(); ep.EndOfDocument(); var length = ep.AbsoluteCharOffset; ep.StartOfDocument(); var originalText = ep.GetText(length); var namer = new ConstraintNamer(originalText); var modifiedText = namer.Go(); if (originalText != modifiedText) { ep.Delete(length); ep.Insert(modifiedText); } } catch (Exception ex) { OutputPane.WriteMessage("Exception naming constraints, error: {0}", ex.Message); } }
public void PrimaryKey() { var scriptPath = ".\\tableOne.sql"; if (File.Exists(scriptPath)) { File.Delete(scriptPath); } File.Copy("..\\..\\..\\ProjectWithConstraints\\TableOne.sql", scriptPath); //var namer = new ConstraintNamer(scriptPath, // "..\\..\\..\\ProjectWithConstraints\\bin\\Release\\ProjectWithConstraints.dacpac"); var namer = new ConstraintNamer(File.ReadAllText(scriptPath)); var changedText = namer.Go(); Assert.LessOrEqual(-1, changedText.IndexOf("[Id] INT NOT NULL PRIMARY KEY"), changedText); Assert.Greater(changedText.IndexOf("CONSTRAINT [PK_TableOne] PRIMARY KEY ([Id])", StringComparison.OrdinalIgnoreCase), -1, changedText); }
private void GenerateKeyAttribute(IProperty property) { var key = property.AsProperty().PrimaryKey; if (key?.Properties.Count == 1) { if (key is Key concreteKey && key.Properties.SequenceEqual(new KeyDiscoveryConvention(null).DiscoverKeyProperties(concreteKey.DeclaringEntityType, concreteKey.DeclaringEntityType.GetProperties().ToList()))) { return; } if (key.Relational().Name != ConstraintNamer.GetDefaultName(key)) { return; } PropertyAnnotationsData.Add(new Dictionary <string, object> { { "property-annotation", new AttributeWriter(nameof(KeyAttribute)) }, }); } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected virtual IMutableForeignKey VisitForeignKey([NotNull] ModelBuilder modelBuilder, [NotNull] DatabaseForeignKey foreignKey) { Check.NotNull(modelBuilder, nameof(modelBuilder)); Check.NotNull(foreignKey, nameof(foreignKey)); if (foreignKey.PrincipalTable == null) { _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPrincipalTableNotFound(foreignKey.DisplayName())); return(null); } if (foreignKey.Table == null) { return(null); } var dependentEntityType = modelBuilder.Model.FindEntityType(GetEntityTypeName(foreignKey.Table)); if (dependentEntityType == null) { return(null); } var unmappedDependentColumns = foreignKey.Columns .Where(c => _unmappedColumns.Contains(c)) .Select(c => c.Name) .ToList(); if (unmappedDependentColumns.Count > 0) { _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPropertyNotFound( foreignKey.DisplayName(), string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, unmappedDependentColumns))); return(null); } var dependentProperties = foreignKey.Columns .Select(GetPropertyName) .Select(name => dependentEntityType.FindProperty(name)) .ToList() .AsReadOnly(); var principalEntityType = modelBuilder.Model.FindEntityType(GetEntityTypeName(foreignKey.PrincipalTable)); if (principalEntityType == null) { _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPrincipalTableScaffoldingError( foreignKey.DisplayName(), foreignKey.PrincipalTable.DisplayName())); return(null); } var unmappedPrincipalColumns = foreignKey.PrincipalColumns .Where(pc => principalEntityType.FindProperty(GetPropertyName(pc)) == null) .Select(pc => pc.Name) .ToList(); if (unmappedPrincipalColumns.Count > 0) { _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPropertyNotFound( foreignKey.DisplayName(), string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, unmappedPrincipalColumns))); return(null); } var principalPropertiesMap = foreignKey.PrincipalColumns .Select( fc => (property: principalEntityType.FindProperty(GetPropertyName(fc)), column: fc)).ToList(); var principalProperties = principalPropertiesMap .Select(tuple => tuple.property) .ToList(); var principalKey = principalEntityType.FindKey(principalProperties); if (principalKey == null) { var index = principalEntityType.FindIndex(principalProperties.AsReadOnly()); if (index?.IsUnique == true) { // ensure all principal properties are non-nullable even if the columns // are nullable on the database. EF's concept of a key requires this. var nullablePrincipalProperties = principalPropertiesMap.Where(tuple => tuple.property.IsNullable).ToList(); if (nullablePrincipalProperties.Count > 0) { _reporter.WriteWarning( DesignStrings.ForeignKeyPrincipalEndContainsNullableColumns( foreignKey.DisplayName(), index.Relational().Name, nullablePrincipalProperties.Select(tuple => tuple.column.DisplayName()).ToList() .Aggregate((a, b) => a + "," + b))); nullablePrincipalProperties .ToList() .ForEach(tuple => tuple.property.IsNullable = false); } principalKey = principalEntityType.AddKey(principalProperties); } else { var principalColumns = foreignKey.PrincipalColumns.Select(c => c.Name).ToList(); _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPrincipalKeyNotFound( foreignKey.DisplayName(), string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, principalColumns), principalEntityType.DisplayName())); return(null); } } var key = dependentEntityType.GetOrAddForeignKey( dependentProperties, principalKey, principalEntityType); var dependentKey = dependentEntityType.FindKey(dependentProperties); var dependentIndex = dependentEntityType.FindIndex(dependentProperties); key.IsUnique = dependentKey != null || dependentIndex?.IsUnique == true; if (!string.IsNullOrEmpty(foreignKey.Name) && foreignKey.Name != ConstraintNamer.GetDefaultName(key)) { key.Relational().Name = foreignKey.Name; } AssignOnDeleteAction(foreignKey, key); key.AddAnnotations(foreignKey.GetAnnotations()); return(key); }
private void GenerateKey(IKey key, bool useDataAnnotations) { if (key == null) { return; } var annotations = key.GetAnnotations().ToList(); var explicitName = key.Relational().Name != ConstraintNamer.GetDefaultName(key); RemoveAnnotation(ref annotations, RelationalAnnotationNames.Name); if (key.Properties.Count == 1 && annotations.Count == 0) { if (key is Key concreteKey && key.Properties.SequenceEqual( new KeyDiscoveryConvention(null).DiscoverKeyProperties( concreteKey.DeclaringEntityType, concreteKey.DeclaringEntityType.GetProperties().ToList()))) { return; } if (!explicitName && useDataAnnotations) { return; } } var lines = new List <string> { $".{nameof(EntityTypeBuilder.HasKey)}(e => {GenerateLambdaToKey(key.Properties, "e")})" }; if (explicitName) { lines.Add( $".{nameof(RelationalKeyBuilderExtensions.HasName)}" + $"({_code.Literal(key.Relational().Name)})"); } var annotationsToRemove = new List <IAnnotation>(); foreach (var annotation in annotations) { if (_annotationCodeGenerator.IsHandledByConvention(key, annotation)) { annotationsToRemove.Add(annotation); } else { var methodCall = _annotationCodeGenerator.GenerateFluentApi(key, annotation); var line = methodCall == null #pragma warning disable CS0618 // Type or member is obsolete ? _annotationCodeGenerator.GenerateFluentApi(key, annotation, Language) #pragma warning restore CS0618 // Type or member is obsolete : _code.Fragment(methodCall); if (line != null) { lines.Add(line); annotationsToRemove.Add(annotation); } } } lines.AddRange(GenerateAnnotations(annotations.Except(annotationsToRemove))); AppendMultiLineFluentApi(key.DeclaringEntityType, lines); }
private void GenerateKey(IKey key, bool useDataAnnotations, IndentedStringBuilder sb) { if (key == null) { return; } var annotations = key.GetAnnotations().ToList(); var explicitName = key.Relational().Name != ConstraintNamer.GetDefaultName(key); RemoveAnnotation(ref annotations, RelationalAnnotationNames.Name); if (key.Properties.Count == 1) { if (key is Key concreteKey && key.Properties.SequenceEqual(new KeyDiscoveryConvention().DiscoverKeyProperties(concreteKey.DeclaringEntityType, concreteKey.DeclaringEntityType.GetProperties().ToList()))) { return; } if (!explicitName && useDataAnnotations) { return; } } var lines = new List <string> { $".{nameof(EntityTypeBuilder.HasKey)}(e => {GenerateLambdaToKey(key.Properties, "e")})" }; if (explicitName) { lines.Add($".{nameof(RelationalKeyBuilderExtensions.HasName)}({CSharpUtilities.DelimitString(key.Relational().Name)})"); } var annotationsToRemove = new List <IAnnotation>(); foreach (var annotation in annotations) { if (_annotationCodeGenerator.IsHandledByConvention(key, annotation)) { annotationsToRemove.Add(annotation); } else { var line = _annotationCodeGenerator.GenerateFluentApi(key, annotation, Language); if (line != null) { lines.Add(line); annotationsToRemove.Add(annotation); } } } lines.AddRange(GenerateAnnotations(annotations.Except(annotationsToRemove))); AppendMultiLineFluentApi(key.DeclaringEntityType, lines, sb); }