Example #1
0
 /// <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));
            }
        }
Example #3
0
        /// <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));
            }
        }
Example #4
0
        /// <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
        }
Example #5
0
        /// <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
        }
Example #6
0
        /// <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
        }
Example #7
0
        /// <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
        }
Example #8
0
        /// <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));
                    }
                }
            }
        }
Example #10
0
        /// <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
        }
Example #11
0
        /// <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;
            }
        }