示例#1
0
        /// <summary>
        /// Sets the <see cref="NpgsqlValueGenerationStrategy" /> to use for the property.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="value">The strategy to use.</param>
        /// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
        public static void SetValueGenerationStrategy(
            [NotNull] this IConventionProperty property, NpgsqlValueGenerationStrategy?value, bool fromDataAnnotation = false)
        {
            CheckValueGenerationStrategy(property, value);

            property.SetOrRemoveAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation);
        }
示例#2
0
        /// <summary>
        /// Sets the <see cref="NpgsqlValueGenerationStrategy" /> to use for the property.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="value">The strategy to use.</param>
        public static void SetValueGenerationStrategy(
            [NotNull] this IMutableProperty property, NpgsqlValueGenerationStrategy?value)
        {
            CheckValueGenerationStrategy(property, value);

            property.SetOrRemoveAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy, value);
        }
        /// <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 new virtual bool ValueGenerationStrategy(NpgsqlValueGenerationStrategy?value)
        {
            if (!SetValueGenerationStrategy(value))
            {
                return(false);
            }

            switch (value)
            {
            case NpgsqlValueGenerationStrategy.SerialColumn:
            case NpgsqlValueGenerationStrategy.IdentityAlwaysColumn:
            case NpgsqlValueGenerationStrategy.IdentityByDefaultColumn:
                PropertyBuilder.ValueGenerated(ValueGenerated.OnAdd, ConfigurationSource.Convention);
                HiLoSequenceName(null);
                HiLoSequenceSchema(null);
                break;

            case NpgsqlValueGenerationStrategy.SequenceHiLo:
                PropertyBuilder.ValueGenerated(ValueGenerated.OnAdd, ConfigurationSource.Convention);
                break;

            case null:
                PropertyBuilder.ValueGenerated(ValueGenerated.Never, ConfigurationSource.Convention);
                HiLoSequenceName(null);
                HiLoSequenceSchema(null);
                break;

            default:
                throw new ArgumentException("Unknown NpgsqlValueGenerationStrategy value: " + value);
            }

            return(true);
        }
        protected virtual bool SetValueGenerationStrategy(NpgsqlValueGenerationStrategy?value)
        {
            if (value != null)
            {
                var propertyType = Property.ClrType;

                if (value == NpgsqlValueGenerationStrategy.SerialColumn && !propertyType.IsIntegerForSerial())
                {
                    throw new ArgumentException($"Serial value generation cannot be used for the property '{Property.Name}' on entity type '{Property.DeclaringEntityType.DisplayName()}' because the property type is '{propertyType.ShortDisplayName()}'. Serial columns can only be of type short, int or long.");
                }

                if (value == NpgsqlValueGenerationStrategy.SequenceHiLo && !propertyType.IsInteger())
                {
                    throw new ArgumentException($"PostgreSQL sequences cannot be used to generate values for the property '{Property.Name}' on entity type '{Property.DeclaringEntityType.DisplayName()}' because the property type is '{propertyType.ShortDisplayName()}'. Sequences can only be used with integer properties.");
                }
            }

            if (!CanSetValueGenerationStrategy(value))
            {
                return(false);
            }

            if (!ShouldThrowOnConflict &&
                ValueGenerationStrategy != value &&
                value != null)
            {
                ClearAllServerGeneratedValues();
            }

            return(Annotations.SetAnnotation(NpgsqlFullAnnotationNames.Instance.ValueGenerationStrategy, null, value));
        }
        /// <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 new virtual bool ValueGenerationStrategy(NpgsqlValueGenerationStrategy?value)
        {
            if (!SetValueGenerationStrategy(value))
            {
                return(false);
            }

            if (value == null)
            {
                PropertyBuilder.ValueGenerated(ValueGenerated.Never, ConfigurationSource.Convention);
                HiLoSequenceName(null);
                HiLoSequenceSchema(null);
            }
            else if (value.Value == NpgsqlValueGenerationStrategy.SerialColumn)
            {
                PropertyBuilder.ValueGenerated(ValueGenerated.OnAdd, ConfigurationSource.Convention);
                HiLoSequenceName(null);
                HiLoSequenceSchema(null);
            }
            else if (value.Value == NpgsqlValueGenerationStrategy.SequenceHiLo)
            {
                PropertyBuilder.ValueGenerated(ValueGenerated.OnAdd, ConfigurationSource.Convention);
            }

            return(true);
        }
        /// <summary>
        ///     Attempts to set the <see cref="NpgsqlValueGenerationStrategy" /> to use for properties
        ///     of keys in the model that don't have a strategy explicitly set.
        /// </summary>
        /// <param name="model"> The model. </param>
        /// <param name="value"> The value to set. </param>
        /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
        public static NpgsqlValueGenerationStrategy?SetValueGenerationStrategy(
            this IConventionModel model,
            NpgsqlValueGenerationStrategy?value,
            bool fromDataAnnotation = false)
        {
            model.SetOrRemoveAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation);

            return(value);
        }
    /// <summary>
    ///     Returns a value indicating whether the given value can be set as the default value generation strategy.
    /// </summary>
    /// <param name="modelBuilder"> The model builder. </param>
    /// <param name="valueGenerationStrategy"> The value generation strategy. </param>
    /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
    /// <returns> <c>true</c> if the given value can be set as the default value generation strategy. </returns>
    public static bool CanSetValueGenerationStrategy(
        this IConventionModelBuilder modelBuilder,
        NpgsqlValueGenerationStrategy?valueGenerationStrategy,
        bool fromDataAnnotation = false)
    {
        Check.NotNull(modelBuilder, nameof(modelBuilder));

        return(modelBuilder.CanSetAnnotation(
                   NpgsqlAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy, fromDataAnnotation));
    }
示例#8
0
        /// <summary>
        /// Returns a value indicating whether the given value can be set as the value generation strategy.
        /// </summary>
        /// <param name="propertyBuilder">The builder for the property being configured.</param>
        /// <param name="valueGenerationStrategy">The value generation strategy.</param>
        /// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
        /// <returns><c>true</c> if the given value can be set as the default value generation strategy.</returns>
        public static bool CanSetValueGenerationStrategy(
            [NotNull] this IConventionPropertyBuilder propertyBuilder,
            NpgsqlValueGenerationStrategy?valueGenerationStrategy,
            bool fromDataAnnotation = false)
        {
            Check.NotNull(propertyBuilder, nameof(propertyBuilder));

            return((valueGenerationStrategy == null ||
                    NpgsqlPropertyExtensions.IsCompatibleWithValueGeneration(propertyBuilder.Metadata)) &&
                   propertyBuilder.CanSetAnnotation(
                       NpgsqlAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy, fromDataAnnotation));
        }
示例#9
0
        /// <summary>
        /// Configures the value generation strategy for the key property, when targeting PostgreSQL.
        /// </summary>
        /// <param name="propertyBuilder">The builder for the property being configured.</param>
        /// <param name="valueGenerationStrategy">The value generation strategy.</param>
        /// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
        /// <returns>
        /// The same builder instance if the configuration was applied, <c>null</c> otherwise.
        /// </returns>
        public static IConventionPropertyBuilder HasValueGenerationStrategy(
            [NotNull] this IConventionPropertyBuilder propertyBuilder,
            NpgsqlValueGenerationStrategy?valueGenerationStrategy,
            bool fromDataAnnotation = false)
        {
            if (propertyBuilder.CanSetAnnotation(
                    NpgsqlAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy, fromDataAnnotation))
            {
                propertyBuilder.Metadata.SetValueGenerationStrategy(valueGenerationStrategy, fromDataAnnotation);
                if (valueGenerationStrategy != NpgsqlValueGenerationStrategy.SequenceHiLo)
                {
                    propertyBuilder.HasHiLoSequence(null, null, fromDataAnnotation);
                }

                return(propertyBuilder);
            }

            return(null);
        }
    /// <summary>
    /// Configures the value generation strategy for the key property, when targeting PostgreSQL.
    /// </summary>
    /// <param name="modelBuilder">The builder for the property being configured.</param>
    /// <param name="valueGenerationStrategy">The value generation strategy.</param>
    /// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
    /// <returns>
    /// The same builder instance if the configuration was applied, <c>null</c> otherwise.
    /// </returns>
    public static IConventionModelBuilder?HasValueGenerationStrategy(
        this IConventionModelBuilder modelBuilder,
        NpgsqlValueGenerationStrategy?valueGenerationStrategy,
        bool fromDataAnnotation = false)
    {
        if (modelBuilder.CanSetAnnotation(
                NpgsqlAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy, fromDataAnnotation))
        {
            modelBuilder.Metadata.SetValueGenerationStrategy(valueGenerationStrategy, fromDataAnnotation);
            if (valueGenerationStrategy != NpgsqlValueGenerationStrategy.SequenceHiLo)
            {
                modelBuilder.HasHiLoSequence(null, null, fromDataAnnotation);
            }

            return(modelBuilder);
        }

        return(null);
    }
示例#11
0
        /// <inheritdoc />
        public virtual void ProcessModelFinalizing(
            IConventionModelBuilder modelBuilder, IConventionContext <IConventionModelBuilder> context)
        {
            foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
            {
                foreach (var property in entityType.GetDeclaredProperties())
                {
                    NpgsqlValueGenerationStrategy?strategy = null;
                    var table = entityType.GetTableName();
                    if (table != null)
                    {
                        var storeObject = StoreObjectIdentifier.Table(table, entityType.GetSchema());
                        strategy = property.GetValueGenerationStrategy(storeObject, Dependencies.TypeMappingSource);
                        if (strategy == NpgsqlValueGenerationStrategy.None &&
                            !IsStrategyNoneNeeded(property, storeObject))
                        {
                            strategy = null;
                        }
                    }
                    else
                    {
                        var view = entityType.GetViewName();
                        if (view != null)
                        {
                            var storeObject = StoreObjectIdentifier.View(view, entityType.GetViewSchema());
                            strategy = property.GetValueGenerationStrategy(storeObject, Dependencies.TypeMappingSource);
                            if (strategy == NpgsqlValueGenerationStrategy.None &&
                                !IsStrategyNoneNeeded(property, storeObject))
                            {
                                strategy = null;
                            }
                        }
                    }

                    // Needed for the annotation to show up in the model snapshot
                    if (strategy != null)
                    {
                        property.Builder.HasValueGenerationStrategy(strategy);
                    }
                }
            }
        protected virtual bool CanSetValueGenerationStrategy(NpgsqlValueGenerationStrategy?value)
        {
            if (GetNpgsqlValueGenerationStrategy(fallbackToModel: false) == value)
            {
                return(true);
            }

            if (!Annotations.CanSetAnnotation(NpgsqlFullAnnotationNames.Instance.ValueGenerationStrategy, null, value))
            {
                return(false);
            }

            if (ShouldThrowOnConflict)
            {
                if (GetDefaultValue(false) != null)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.ConflictingColumnServerGeneration(nameof(ValueGenerationStrategy), Property.Name, nameof(DefaultValue)));
                }
                if (GetDefaultValueSql(false) != null)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.ConflictingColumnServerGeneration(nameof(ValueGenerationStrategy), Property.Name, nameof(DefaultValueSql)));
                }
                if (GetComputedColumnSql(false) != null)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.ConflictingColumnServerGeneration(nameof(ValueGenerationStrategy), Property.Name, nameof(ComputedColumnSql)));
                }
            }
            else if (value != null &&
                     (!CanSetDefaultValue(null) ||
                      !CanSetDefaultValueSql(null) ||
                      !CanSetComputedColumnSql(null)))
            {
                return(false);
            }

            return(true);
        }
示例#13
0
        static void CheckValueGenerationStrategy(IProperty property, NpgsqlValueGenerationStrategy?value)
        {
            if (value != null)
            {
                var propertyType = property.ClrType;

                if (value == NpgsqlValueGenerationStrategy.SerialColumn && !propertyType.IsIntegerForValueGeneration())
                {
                    throw new ArgumentException($"Serial value generation cannot be used for the property '{property.Name}' on entity type '{property.DeclaringEntityType.DisplayName()}' because the property type is '{propertyType.ShortDisplayName()}'. Serial columns can only be of type short, int or long.");
                }

                if ((value == NpgsqlValueGenerationStrategy.IdentityAlwaysColumn || value == NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) &&
                    !propertyType.IsIntegerForValueGeneration())
                {
                    throw new ArgumentException($"Identity value generation cannot be used for the property '{property.Name}' on entity type '{property.DeclaringEntityType.DisplayName()}' because the property type is '{propertyType.ShortDisplayName()}'. Identity columns can only be of type short, int or long.");
                }

                if (value == NpgsqlValueGenerationStrategy.SequenceHiLo && !propertyType.IsInteger())
                {
                    throw new ArgumentException($"PostgreSQL sequences cannot be used to generate values for the property '{property.Name}' on entity type '{property.DeclaringEntityType.DisplayName()}' because the property type is '{propertyType.ShortDisplayName()}'. Sequences can only be used with integer properties.");
                }
            }
        }
示例#14
0
 /// <summary>
 ///     Attempts to set the <see cref="NpgsqlValueGenerationStrategy" /> to use for properties
 ///     of keys in the model that don't have a strategy explicitly set.
 /// </summary>
 /// <param name="model"> The model. </param>
 /// <param name="value"> The value to set. </param>
 /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
 public static void SetValueGenerationStrategy(
     [NotNull] this IConventionModel model, NpgsqlValueGenerationStrategy?value, bool fromDataAnnotation = false)
 => model.SetOrRemoveAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation);
示例#15
0
 /// <summary>
 ///     Attempts to set the <see cref="NpgsqlValueGenerationStrategy" /> to use for properties
 ///     of keys in the model that don't have a strategy explicitly set.
 /// </summary>
 /// <param name="model"> The model. </param>
 /// <param name="value"> The value to set. </param>
 public static void SetValueGenerationStrategy(this IMutableModel model, NpgsqlValueGenerationStrategy?value)
 => model.SetOrRemoveAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy, value);
    /// <inheritdoc />
    public virtual void ProcessModelFinalizing(
        IConventionModelBuilder modelBuilder, IConventionContext <IConventionModelBuilder> context)
    {
        foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
        {
            foreach (var property in entityType.GetDeclaredProperties())
            {
                NpgsqlValueGenerationStrategy?strategy = null;
                var table = entityType.GetTableName();
                if (table is not null)
                {
                    var storeObject = StoreObjectIdentifier.Table(table, entityType.GetSchema());
                    strategy = property.GetValueGenerationStrategy(storeObject, Dependencies.TypeMappingSource);
                    if (strategy == NpgsqlValueGenerationStrategy.None &&
                        !IsStrategyNoneNeeded(property, storeObject))
                    {
                        strategy = null;
                    }
                }
                else
                {
                    var view = entityType.GetViewName();
                    if (view is not null)
                    {
                        var storeObject = StoreObjectIdentifier.View(view, entityType.GetViewSchema());
                        strategy = property.GetValueGenerationStrategy(storeObject, Dependencies.TypeMappingSource);
                        if (strategy == NpgsqlValueGenerationStrategy.None &&
                            !IsStrategyNoneNeeded(property, storeObject))
                        {
                            strategy = null;
                        }
                    }
                }

                // Needed for the annotation to show up in the model snapshot
                if (strategy is not null)
                {
                    property.Builder.HasValueGenerationStrategy(strategy);
                }
            }
        }

        bool IsStrategyNoneNeeded(IReadOnlyProperty property, StoreObjectIdentifier storeObject)
        {
            if (property.ValueGenerated == ValueGenerated.OnAdd &&
                !property.TryGetDefaultValue(storeObject, out _) &&
                property.GetDefaultValueSql(storeObject) is null &&
                property.GetComputedColumnSql(storeObject) is null &&
                property.DeclaringEntityType.Model.GetValueGenerationStrategy() != NpgsqlValueGenerationStrategy.None)
            {
                var providerClrType = (property.GetValueConverter()
                                       ?? (property.FindRelationalTypeMapping(storeObject)
                                           ?? Dependencies.TypeMappingSource.FindMapping((IProperty)property))?.Converter)
                                      ?.ProviderClrType.UnwrapNullableType();

                return(providerClrType is not null && (providerClrType.IsInteger()));
            }

            return(false);
        }
    }
示例#17
0
 public static bool IsIdentity(this NpgsqlValueGenerationStrategy?strategy)
 => strategy == NpgsqlValueGenerationStrategy.IdentityByDefaultColumn ||
 strategy == NpgsqlValueGenerationStrategy.IdentityAlwaysColumn;
 /// <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 new virtual bool ValueGenerationStrategy(NpgsqlValueGenerationStrategy?value) => SetValueGenerationStrategy(value);
示例#19
0
 protected virtual bool SetValueGenerationStrategy(NpgsqlValueGenerationStrategy?value)
 => Annotations.SetAnnotation(NpgsqlFullAnnotationNames.Instance.ValueGenerationStrategy,
                              null,
                              value);