/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected virtual void ValidateNonKeyValueGeneration([NotNull] IModel model, DiagnosticsLoggers loggers) { foreach (var property in model.GetEntityTypes() .SelectMany(t => t.GetDeclaredProperties()) .Where( p => p.GetSqlServerValueGenerationStrategy() == SqlServerValueGenerationStrategy.SequenceHiLo && ((IConventionProperty)p).GetSqlServerValueGenerationStrategyConfigurationSource() != null && !p.IsKey() && p.ValueGenerated != ValueGenerated.Never && (!(p.FindAnnotation(SqlServerAnnotationNames.ValueGenerationStrategy) is ConventionAnnotation strategy) || !ConfigurationSource.Convention.Overrides(strategy.GetConfigurationSource())))) { throw new InvalidOperationException( SqlServerStrings.NonKeyValueGeneration(property.Name, property.DeclaringEntityType.DisplayName())); } }
/// <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 override void ValidateSharedColumnsCompatibility( IReadOnlyList <IEntityType> mappedTypes, string tableName, DiagnosticsLoggers loggers) { base.ValidateSharedColumnsCompatibility(mappedTypes, tableName, loggers); var identityColumns = new List <IProperty>(); var propertyMappings = new Dictionary <string, IProperty>(); foreach (var property in mappedTypes.SelectMany(et => et.GetDeclaredProperties())) { var propertyAnnotations = property.Relational(); var columnName = propertyAnnotations.ColumnName; if (propertyMappings.TryGetValue(columnName, out var duplicateProperty)) { var propertyStrategy = property.SqlServer().ValueGenerationStrategy; var duplicatePropertyStrategy = duplicateProperty.SqlServer().ValueGenerationStrategy; if (propertyStrategy != duplicatePropertyStrategy && (propertyStrategy == SqlServerValueGenerationStrategy.IdentityColumn || duplicatePropertyStrategy == SqlServerValueGenerationStrategy.IdentityColumn)) { throw new InvalidOperationException( SqlServerStrings.DuplicateColumnNameValueGenerationStrategyMismatch( duplicateProperty.DeclaringEntityType.DisplayName(), duplicateProperty.Name, property.DeclaringEntityType.DisplayName(), property.Name, columnName, tableName)); } } else { propertyMappings[columnName] = property; if (property.SqlServer().ValueGenerationStrategy == SqlServerValueGenerationStrategy.IdentityColumn) { identityColumns.Add(property); } } } if (identityColumns.Count > 1) { var sb = new StringBuilder() .AppendJoin(identityColumns.Select(p => "'" + p.DeclaringEntityType.DisplayName() + "." + p.Name + "'")); throw new InvalidOperationException(SqlServerStrings.MultipleIdentityColumns(sb, tableName)); } }
/// <inheritdoc /> protected override void ValidateCompatible(IKey key, IKey duplicateKey, string keyName, string tableName) { base.ValidateCompatible(key, duplicateKey, keyName, tableName); if (key.IsClustered() != duplicateKey.IsClustered()) { throw new InvalidOperationException( SqlServerStrings.DuplicateKeyMismatchedClustering( key.Properties.Format(), key.DeclaringEntityType.DisplayName(), duplicateKey.Properties.Format(), duplicateKey.DeclaringEntityType.DisplayName(), tableName, keyName)); } }
/// <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> public static void TableFound( [NotNull] this IDiagnosticsLogger <DbLoggerCategory.Scaffolding> diagnostics, [NotNull] string tableName) { var definition = SqlServerStrings.LogFoundTable(diagnostics); var warningBehavior = definition.GetLogBehavior(diagnostics); if (warningBehavior != WarningBehavior.Ignore) { definition.Log( diagnostics, warningBehavior, tableName); } // No DiagnosticsSource events because these are purely design-time messages }
/// <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> public static void MissingSchemaWarning( [NotNull] this IDiagnosticsLogger <DbLoggerCategory.Scaffolding> diagnostics, [CanBeNull] string schemaName) { var definition = SqlServerStrings.LogMissingSchema(diagnostics); var warningBehavior = definition.GetLogBehavior(diagnostics); if (warningBehavior != WarningBehavior.Ignore) { definition.Log( diagnostics, warningBehavior, schemaName); } // No DiagnosticsSource events because these are purely design-time messages }
/// <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> public static void ColumnFound( [NotNull] this IDiagnosticsLogger <DbLoggerCategory.Scaffolding> diagnostics, [NotNull] string tableName, [NotNull] string columnName, int ordinal, [NotNull] string dataTypeName, int maxLength, int precision, int scale, bool nullable, bool identity, [CanBeNull] string defaultValue, [CanBeNull] string computedValue) { var definition = SqlServerStrings.LogFoundColumn(diagnostics); var warningBehavior = definition.GetLogBehavior(diagnostics); if (warningBehavior != WarningBehavior.Ignore) { definition.Log( diagnostics, warningBehavior, l => l.LogDebug( definition.EventId, null, definition.MessageFormat, tableName, columnName, ordinal, dataTypeName, maxLength, precision, scale, nullable, identity, defaultValue, computedValue)); } // No DiagnosticsSource events because these are purely design-time messages }
/// <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> public static void ForeignKeyReferencesMissingPrincipalTableWarning( [NotNull] this IDiagnosticsLogger <DbLoggerCategory.Scaffolding> diagnostics, [CanBeNull] string foreignKeyName, [CanBeNull] string tableName, [CanBeNull] string principalTableName) { var definition = SqlServerStrings.LogPrincipalTableNotInSelectionSet(diagnostics); var warningBehavior = definition.GetLogBehavior(diagnostics); if (warningBehavior != WarningBehavior.Ignore) { definition.Log( diagnostics, warningBehavior, foreignKeyName, tableName, principalTableName); } // No DiagnosticsSource events because these are purely design-time messages }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected override void ValidateSharedTableCompatibility( IReadOnlyList <IEntityType> mappedTypes, string tableName, DiagnosticsLoggers loggers) { var firstMappedType = mappedTypes[0]; var isMemoryOptimized = firstMappedType.GetSqlServerIsMemoryOptimized(); foreach (var otherMappedType in mappedTypes.Skip(1)) { if (isMemoryOptimized != otherMappedType.GetSqlServerIsMemoryOptimized()) { throw new InvalidOperationException( SqlServerStrings.IncompatibleTableMemoryOptimizedMismatch( tableName, firstMappedType.DisplayName(), otherMappedType.DisplayName(), isMemoryOptimized ? firstMappedType.DisplayName() : otherMappedType.DisplayName(), !isMemoryOptimized ? firstMappedType.DisplayName() : otherMappedType.DisplayName())); } } base.ValidateSharedTableCompatibility(mappedTypes, tableName, loggers); }
/// <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 void ValidateIndexIncludeProperties([NotNull] IModel model, DiagnosticsLoggers loggers) { foreach (var index in model.GetEntityTypes().SelectMany(t => t.GetDeclaredIndexes())) { var includeProperties = index.SqlServer().IncludeProperties; if (includeProperties?.Count > 0) { var notFound = includeProperties .Where(i => index.DeclaringEntityType.FindProperty(i) == null) .FirstOrDefault(); if (notFound != null) { throw new InvalidOperationException( SqlServerStrings.IncludePropertyNotFound(index.DeclaringEntityType.DisplayName(), notFound)); } var duplicate = includeProperties .GroupBy(i => i) .Where(g => g.Count() > 1) .Select(y => y.Key) .FirstOrDefault(); if (duplicate != null) { throw new InvalidOperationException( SqlServerStrings.IncludePropertyDuplicated(index.DeclaringEntityType.DisplayName(), duplicate)); } var inIndex = includeProperties .Where(i => index.Properties.Any(p => i == p.Name)) .FirstOrDefault(); if (inIndex != null) { throw new InvalidOperationException( SqlServerStrings.IncludePropertyInIndex(index.DeclaringEntityType.DisplayName(), inIndex)); } } } }
/// <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> public static void ForeignKeyFound( [NotNull] this IDiagnosticsLogger <DbLoggerCategory.Scaffolding> diagnostics, [NotNull] string foreignKeyName, [NotNull] string tableName, [NotNull] string principalTableName, [NotNull] string onDeleteAction) { var definition = SqlServerStrings.LogFoundForeignKey(diagnostics); var warningBehavior = definition.GetLogBehavior(diagnostics); if (warningBehavior != WarningBehavior.Ignore) { definition.Log( diagnostics, warningBehavior, foreignKeyName, tableName, principalTableName, onDeleteAction); } // No DiagnosticsSource events because these are purely design-time messages }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected override void ValidateSharedColumnsCompatibility( IReadOnlyList <IEntityType> mappedTypes, string tableName, IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger) { base.ValidateSharedColumnsCompatibility(mappedTypes, tableName, logger); var identityColumns = new Dictionary <string, IProperty>(); foreach (var property in mappedTypes.SelectMany(et => et.GetDeclaredProperties())) { if (property.GetValueGenerationStrategy() == SqlServerValueGenerationStrategy.IdentityColumn) { identityColumns[property.GetColumnName()] = property; } } if (identityColumns.Count > 1) { var sb = new StringBuilder() .AppendJoin(identityColumns.Values.Select(p => "'" + p.DeclaringEntityType.DisplayName() + "." + p.Name + "'")); throw new InvalidOperationException(SqlServerStrings.MultipleIdentityColumns(sb, tableName)); } }
/// <inheritdoc /> protected override void ValidateCompatible( IProperty property, IProperty duplicateProperty, string columnName, string tableName, string schema, IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger) { base.ValidateCompatible(property, duplicateProperty, columnName, tableName, schema, logger); var propertyStrategy = property.GetValueGenerationStrategy(tableName, schema); var duplicatePropertyStrategy = duplicateProperty.GetValueGenerationStrategy(tableName, schema); if (propertyStrategy != duplicatePropertyStrategy) { throw new InvalidOperationException( SqlServerStrings.DuplicateColumnNameValueGenerationStrategyMismatch( duplicateProperty.DeclaringEntityType.DisplayName(), duplicateProperty.Name, property.DeclaringEntityType.DisplayName(), property.Name, columnName, tableName)); } switch (propertyStrategy) { case SqlServerValueGenerationStrategy.IdentityColumn: var increment = property.GetIdentityIncrement(); var duplicateIncrement = duplicateProperty.GetIdentityIncrement(); if (increment != duplicateIncrement) { throw new InvalidOperationException( SqlServerStrings.DuplicateColumnIdentityIncrementMismatch( duplicateProperty.DeclaringEntityType.DisplayName(), duplicateProperty.Name, property.DeclaringEntityType.DisplayName(), property.Name, columnName, tableName)); } var seed = property.GetIdentitySeed(); var duplicateSeed = duplicateProperty.GetIdentitySeed(); if (seed != duplicateSeed) { throw new InvalidOperationException( SqlServerStrings.DuplicateColumnIdentitySeedMismatch( duplicateProperty.DeclaringEntityType.DisplayName(), duplicateProperty.Name, property.DeclaringEntityType.DisplayName(), property.Name, columnName, tableName)); } break; case SqlServerValueGenerationStrategy.SequenceHiLo: if (property.GetHiLoSequenceName() != duplicateProperty.GetHiLoSequenceName() || property.GetHiLoSequenceSchema() != duplicateProperty.GetHiLoSequenceSchema()) { throw new InvalidOperationException( SqlServerStrings.DuplicateColumnSequenceMismatch( duplicateProperty.DeclaringEntityType.DisplayName(), duplicateProperty.Name, property.DeclaringEntityType.DisplayName(), property.Name, columnName, tableName)); } break; } }