예제 #1
0
        /// <summary>
        ///     <para>
        ///         Returns the <see cref="MySqlValueGenerationStrategy" /> to use for the property.
        ///     </para>
        ///     <para>
        ///         If no strategy is set for the property, then the strategy to use will be taken from the <see cref="IModel" />.
        ///     </para>
        /// </summary>
        /// <returns> The strategy, or <see cref="MySqlValueGenerationStrategy.None"/> if none was set. </returns>
        public static MySqlValueGenerationStrategy?GetValueGenerationStrategy([NotNull] this IReadOnlyProperty property, StoreObjectIdentifier storeObject = default)
        {
            var annotation = property[MySqlAnnotationNames.ValueGenerationStrategy];

            if (annotation != null)
            {
                return((MySqlValueGenerationStrategy?)annotation);
            }

            if (property.GetDefaultValue() != null || property.GetDefaultValueSql() != null || property.GetComputedColumnSql() != null)
            {
                return(null);
            }

            if (storeObject != default &&
                property.ValueGenerated == ValueGenerated.Never)
            {
                return(property.FindSharedStoreObjectRootProperty(storeObject)
                       ?.GetValueGenerationStrategy(storeObject));
            }

            if (IsCompatibleIdentityColumn(property) && property.ValueGenerated == ValueGenerated.OnAdd)
            {
                return(MySqlValueGenerationStrategy.IdentityColumn);
            }

            if (IsCompatibleComputedColumn(property) && property.ValueGenerated == ValueGenerated.OnAddOrUpdate)
            {
                return(MySqlValueGenerationStrategy.ComputedColumn);
            }

            return(null);
        }
예제 #2
0
 public static PropertySaveBehavior GetAfterSaveBehavior([NotNull] this IReadOnlyProperty property)
 => (PropertySaveBehavior?)Check.NotNull(property, nameof(property))[CoreAnnotationNames.AfterSaveBehavior]
 ?? (property.IsKey()
             ? PropertySaveBehavior.Throw
             : property.ValueGenerated.ForUpdate()
                 ? PropertySaveBehavior.Ignore
                 : PropertySaveBehavior.Save);
예제 #3
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>
 public static bool RequiresValueGenerator(this IReadOnlyProperty property)
 => (property.ValueGenerated.ForAdd() &&
     property.IsKey() &&
     (!property.IsForeignKey() ||
      property.IsForeignKeyToSelf() ||
      (property.GetContainingForeignKeys().All(fk => fk.Properties.Any(p => p != property && p.IsNullable))))) ||
 property.GetValueGeneratorFactory() != null;
예제 #4
0
        public static ValueComparer?GetKeyValueComparer([NotNull] this IReadOnlyProperty property)
        {
            Check.NotNull(property, nameof(property));

            return((ValueComparer?)property[CoreAnnotationNames.ValueComparer]
                   ?? property.FindTypeMapping()?.KeyComparer);
        }
예제 #5
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>
        public static void ConflictingValueGenerationStrategiesWarning(
            [NotNull] this IDiagnosticsLogger <DbLoggerCategory.Model.Validation> diagnostics,
            SqlServerValueGenerationStrategy sqlServerValueGenerationStrategy,
            [NotNull] string otherValueGenerationStrategy,
            [NotNull] IReadOnlyProperty property)
        {
            var definition = SqlServerResources.LogConflictingValueGenerationStrategies(diagnostics);

            if (diagnostics.ShouldLog(definition))
            {
                definition.Log(
                    diagnostics, sqlServerValueGenerationStrategy.ToString(), otherValueGenerationStrategy,
                    property.Name, property.DeclaringEntityType.DisplayName());
            }

            if (diagnostics.NeedsEventData(definition, out var diagnosticSourceEnabled, out var simpleLogEnabled))
            {
                var eventData = new ConflictingValueGenerationStrategiesEventData(
                    definition,
                    ConflictingValueGenerationStrategiesWarning,
                    sqlServerValueGenerationStrategy,
                    otherValueGenerationStrategy,
                    property);

                diagnostics.DispatchEventData(definition, eventData, diagnosticSourceEnabled, simpleLogEnabled);
            }
        }
예제 #6
0
        /// <summary>
        ///     Returns a value indicating whether the property is compatible with <see cref="MySqlValueGenerationStrategy.ComputedColumn"/>.
        /// </summary>
        /// <param name="property"> The property. </param>
        /// <returns> <see langword="true"/> if compatible. </returns>
        public static bool IsCompatibleComputedColumn(IReadOnlyProperty property)
        {
            var type = property.ClrType;

            // RowVersion uses byte[] and the BytesToDateTimeConverter.
            return((type == typeof(DateTime) || type == typeof(DateTimeOffset)) && !HasConverter(property) ||
                   type == typeof(byte[]) && !HasExternalConverter(property));
        }
예제 #7
0
        /// <summary>
        ///     Returns a value indicating whether the property is compatible with a `CURRENT_TIMESTAMP` column default.
        /// </summary>
        /// <param name="property"> The property. </param>
        /// <returns> <see langword="true"/> if compatible. </returns>
        public static bool IsCompatibleCurrentTimestampColumn(IReadOnlyProperty property)
        {
            var valueConverter = GetConverter(property);
            var type           = (valueConverter?.ProviderClrType ?? property.ClrType).UnwrapNullableType();

            return(type == typeof(DateTime) ||
                   type == typeof(DateTimeOffset));
        }
예제 #8
0
        /// <summary>
        ///     Returns a value indicating whether the property is compatible with an `AUTO_INCREMENT` column.
        /// </summary>
        /// <param name="property"> The property. </param>
        /// <returns> <see langword="true"/> if compatible. </returns>
        public static bool IsCompatibleAutoIncrementColumn(IReadOnlyProperty property)
        {
            var valueConverter = GetConverter(property);
            var type           = (valueConverter?.ProviderClrType ?? property.ClrType).UnwrapNullableType();

            return(type.IsInteger() ||
                   type == typeof(decimal));
        }
예제 #9
0
 /// <summary>
 ///     Constructs the event payload.
 /// </summary>
 /// <param name="eventDefinition">The event definition.</param>
 /// <param name="messageGenerator">A delegate that generates a log message for this event.</param>
 /// <param name="property">The property.</param>
 public PropertyEventData(
     EventDefinitionBase eventDefinition,
     Func <EventDefinitionBase, EventData, string> messageGenerator,
     IReadOnlyProperty property)
     : base(eventDefinition, messageGenerator)
 {
     Property = property;
 }
예제 #10
0
 /// <summary>
 ///     Constructs the event payload.
 /// </summary>
 /// <param name="eventDefinition">The event definition.</param>
 /// <param name="messageGenerator">A delegate that generates a log message for this event.</param>
 /// <param name="property">The property.</param>
 /// <param name="basePropertyName">The property name that was uniquified.</param>
 public UniquifiedPropertyEventData(
     EventDefinitionBase eventDefinition,
     Func <EventDefinitionBase, EventData, string> messageGenerator,
     IReadOnlyProperty property,
     string basePropertyName)
     : base(eventDefinition, messageGenerator, property)
 {
     BasePropertyName = basePropertyName;
 }
예제 #11
0
        public static IReadOnlyList <IReadOnlyProperty> FindPrincipals([NotNull] this IReadOnlyProperty property)
        {
            var principals = new List <IReadOnlyProperty> {
                property
            };

            AddPrincipals(property, principals);
            return(principals);
        }
예제 #12
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>
        public static int IndexOf(this IReadOnlyKey key, IReadOnlyProperty property)
        {
            var index = 0;

            for (; index < key.Properties.Count && key.Properties[index] != property; index++)
            {
            }

            return(index == key.Properties.Count ? -1 : index);
        }
예제 #13
0
        public static CoreTypeMapping GetTypeMapping([NotNull] this IReadOnlyProperty property)
        {
            var mapping = ((Property)property).TypeMapping;

            if (mapping == null)
            {
                throw new InvalidOperationException(CoreStrings.ModelNotFinalized(nameof(GetTypeMapping)));
            }

            return(mapping);
        }
 /// <summary>
 ///     Constructs the event payload.
 /// </summary>
 /// <param name="eventDefinition">The event definition.</param>
 /// <param name="messageGenerator">A delegate that generates a log message for this event.</param>
 /// <param name="sqlServerValueGenerationStrategy">The SQL Server value generation strategy.</param>
 /// <param name="otherValueGenerationStrategy">The other value generation strategy.</param>
 /// <param name="property">The property.</param>
 public ConflictingValueGenerationStrategiesEventData(
     EventDefinitionBase eventDefinition,
     Func <EventDefinitionBase, EventData, string> messageGenerator,
     SqlServerValueGenerationStrategy sqlServerValueGenerationStrategy,
     string otherValueGenerationStrategy,
     IReadOnlyProperty property)
     : base(eventDefinition, messageGenerator)
 {
     SqlServerValueGenerationStrategy = sqlServerValueGenerationStrategy;
     OtherValueGenerationStrategy     = otherValueGenerationStrategy;
     Property = property;
 }
예제 #15
0
        public static bool IsOrdinalKeyProperty([NotNull] this IReadOnlyProperty property)
        {
            Check.DebugAssert(
                property.DeclaringEntityType.IsOwned(), $"Expected {property.DeclaringEntityType.DisplayName()} to be owned.");
            Check.DebugAssert(property.GetJsonPropertyName().Length == 0, $"Expected {property.Name} to be non-persisted.");

            return(property.FindContainingPrimaryKey() is IReadOnlyKey key &&
                   key.Properties.Count > 1 &&
                   !property.IsForeignKey() &&
                   property.ClrType == typeof(int) &&
                   property.ValueGenerated == ValueGenerated.OnAdd);
        }
예제 #16
0
        public static bool IsForeignKeyToSelf([NotNull] this IReadOnlyProperty property)
        {
            Check.DebugAssert(property.IsKey(), "Only call this method for properties known to be part of a key.");

            foreach (var foreignKey in property.GetContainingForeignKeys())
            {
                var propertyIndex = foreignKey.Properties.IndexOf(property);
                if (propertyIndex == foreignKey.PrincipalKey.Properties.IndexOf(property))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #17
0
            static bool IsStrategyNoneNeeded(IReadOnlyProperty property, StoreObjectIdentifier storeObject)
            {
                if (property.ValueGenerated == ValueGenerated.OnAdd &&
                    property.GetDefaultValue(storeObject) == null &&
                    property.GetDefaultValueSql(storeObject) == null &&
                    property.GetComputedColumnSql(storeObject) == null &&
                    property.DeclaringEntityType.Model.GetValueGenerationStrategy() != NpgsqlValueGenerationStrategy.None)
                {
                    var providerClrType = (property.GetValueConverter() ?? property.FindRelationalTypeMapping(storeObject)?.Converter)
                                          ?.ProviderClrType.UnwrapNullableType();

                    return(providerClrType != null && (providerClrType.IsInteger()));
                }

                return(false);
            }
예제 #18
0
        private static string GetDefaultJsonPropertyName(IReadOnlyProperty property)
        {
            var entityType = property.DeclaringEntityType;
            var ownership  = entityType.FindOwnership();

            if (ownership != null &&
                !entityType.IsDocumentRoot())
            {
                var pk = property.FindContainingPrimaryKey();
                if (pk != null &&
                    (property.ClrType == typeof(int) || ownership.Properties.Contains(property)) &&
                    pk.Properties.Count == ownership.Properties.Count + (ownership.IsUnique ? 0 : 1) &&
                    ownership.Properties.All(fkProperty => pk.Properties.Contains(fkProperty)))
                {
                    return("");
                }
            }

            return(property.Name);
        }
예제 #19
0
        /// <summary>
        ///     <para>
        ///         Returns the <see cref="MySqlValueGenerationStrategy" /> to use for the property.
        ///     </para>
        ///     <para>
        ///         If no strategy is set for the property, then the strategy to use will be taken from the <see cref="IModel" />.
        ///     </para>
        /// </summary>
        /// <returns> The strategy, or <see cref="MySqlValueGenerationStrategy.None"/> if none was set. </returns>
        public static MySqlValueGenerationStrategy?GetValueGenerationStrategy([NotNull] this IReadOnlyProperty property, StoreObjectIdentifier storeObject = default)
        {
            var annotation = property[MySqlAnnotationNames.ValueGenerationStrategy];

            if (annotation != null)
            {
                // Allow users to use the underlying type value instead of the enum itself.
                // Workaround for: https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/issues/1205
                //return ObjectToEnumConverter.GetEnumValue<MySqlValueGenerationStrategy>(annotation);
                return(ObjectToEnumConverter.GetEnumValue <MySqlValueGenerationStrategy>(annotation));
            }

            if (property.GetContainingForeignKeys().Any(fk => !fk.IsBaseLinking()) ||
                property.TryGetDefaultValue(storeObject, out _) ||
                property.GetDefaultValueSql() != null ||
                property.GetComputedColumnSql() != null)
            {
                return(null);
            }

            if (storeObject != default &&
                property.ValueGenerated == ValueGenerated.Never)
            {
                return(property.FindSharedStoreObjectRootProperty(storeObject)
                       ?.GetValueGenerationStrategy(storeObject));
            }

            if (property.ValueGenerated == ValueGenerated.OnAdd &&
                IsCompatibleIdentityColumn(property))
            {
                return(MySqlValueGenerationStrategy.IdentityColumn);
            }

            if (property.ValueGenerated == ValueGenerated.OnAddOrUpdate &&
                IsCompatibleComputedColumn(property))
            {
                return(MySqlValueGenerationStrategy.ComputedColumn);
            }

            return(null);
        }
예제 #20
0
        public static IReadOnlyProperty?FindFirstPrincipal([NotNull] this IReadOnlyProperty property)
        {
            Check.NotNull(property, nameof(property));

            var concreteProperty = property.AsProperty();

            if (concreteProperty.ForeignKeys != null)
            {
                foreach (var foreignKey in concreteProperty.ForeignKeys)
                {
                    for (var propertyIndex = 0; propertyIndex < foreignKey.Properties.Count; propertyIndex++)
                    {
                        if (property == foreignKey.Properties[propertyIndex])
                        {
                            return(foreignKey.PrincipalKey.Properties[propertyIndex]);
                        }
                    }
                }
            }

            return(null);
        }
예제 #21
0
        private static void CheckValueGenerationStrategy(IReadOnlyProperty property, MySqlValueGenerationStrategy?value)
        {
            if (value != null)
            {
                var propertyType = property.ClrType;

                if (value == MySqlValueGenerationStrategy.IdentityColumn &&
                    !IsCompatibleIdentityColumn(property))
                {
                    throw new ArgumentException(
                              MySqlStrings.IdentityBadType(
                                  property.Name, property.DeclaringEntityType.DisplayName(), propertyType.ShortDisplayName()));
                }

                if (value == MySqlValueGenerationStrategy.ComputedColumn &&
                    !IsCompatibleComputedColumn(property))
                {
                    throw new ArgumentException(
                              MySqlStrings.ComputedBadType(
                                  property.Name, property.DeclaringEntityType.DisplayName(), propertyType.ShortDisplayName()));
                }
            }
        }
예제 #22
0
        private static void AddPrincipals(IReadOnlyProperty property, List <IReadOnlyProperty> visited)
        {
            var concreteProperty = property.AsProperty();

            if (concreteProperty.ForeignKeys != null)
            {
                foreach (var foreignKey in concreteProperty.ForeignKeys)
                {
                    for (var propertyIndex = 0; propertyIndex < foreignKey.Properties.Count; propertyIndex++)
                    {
                        if (property == foreignKey.Properties[propertyIndex])
                        {
                            var principal = foreignKey.PrincipalKey.Properties[propertyIndex];
                            if (!visited.Contains(principal))
                            {
                                visited.Add(principal);

                                AddPrincipals(principal, visited);
                            }
                        }
                    }
                }
            }
        }
예제 #23
0
 public Main3ViewModel()
 {
     this.calculator = ObservablePropertyFactory.Instance.CreateReadOnlyProperty(new CalculatorViewModel(false));
 }
예제 #24
0
        public CalculatorViewModel(bool supportsAsync)
        {
            this.updateInRealTimeItems =
                ObservablePropertyFactory.Instance.CreateReadOnlyProperty(
                    ObservableCollectionFactory.Instance.CreateObservableCollection(new[] { true, false }));
            this.updateInRealTimeSelection = ObservablePropertyFactory.Instance.CreateProperty<bool?>(true);
            this.updateInRealTime =
                ObservablePropertyFactory.Instance.CreateCalculatedProperty(
                    this.updateInRealTimeSelection,
                    updateInRealTimeSelection => updateInRealTimeSelection.HasValue && updateInRealTimeSelection.Value);
            this.supportsAsync = ObservablePropertyFactory.Instance.CreateReadOnlyProperty(supportsAsync);
            this.simulateLatencyItems =
                ObservablePropertyFactory.Instance.CreateReadOnlyProperty(
                    ObservableCollectionFactory.Instance.CreateObservableCollection(new[] { true, false }));
            this.simulateLatencySelection = ObservablePropertyFactory.Instance.CreateProperty<bool?>(true);
            this.simulateLatency =
                ObservablePropertyFactory.Instance.CreateCalculatedProperty(
                    this.simulateLatencySelection,
                    simulateLatencySelection => simulateLatencySelection.HasValue && simulateLatencySelection.Value);
            this.operators =
                ObservablePropertyFactory.Instance.CreateReadOnlyProperty(
                    ObservableCollectionFactory.Instance.CreateObservableCollection(
                        new[] { Operator.Add, Operator.Subtract, Operator.Multiply, Operator.Divide }));
            this.showMultiply =
                ObservablePropertyFactory.Instance.CreateCalculatedProperty(
                    this.operators.MergeCollectionPropertyWithChanges(this.operators),
                    c => c.Collection.Contains(Operator.Multiply));
            this.showDivide =
                ObservablePropertyFactory.Instance.CreateCalculatedProperty(
                    this.operators.MergeCollectionPropertyWithChanges(this.operators),
                    c => c.Collection.Contains(Operator.Divide));
            this.operand1 = ObservablePropertyFactory.Instance.CreateProperty<string>(null);
            this.selectedOperator = ObservablePropertyFactory.Instance.CreateProperty(Operator.Add);
            this.selectedOperatorString =
                ObservablePropertyFactory.Instance.CreateCalculatedProperty(
                    this.selectedOperator,
                    selectedOperator =>
                        {
                            switch (selectedOperator)
                            {
                                case Operator.Add:
                                    return "+";
                                case Operator.Subtract:
                                    return "-";
                                case Operator.Multiply:
                                    return "*";
                                case Operator.Divide:
                                    return "/";
                                default:
                                    throw new NotSupportedException(
                                        "Unknown enumeration value " + selectedOperator + ".");
                            }
                        });
            this.operand2 = ObservablePropertyFactory.Instance.CreateProperty<string>(null);
            this.result = ObservablePropertyFactory.Instance.CreateCalculatedProperty(
                this.Operand1,
                this.Operand2,
                this.SelectedOperator,
                (operand1, operand2, selectedOperator) =>
                    {
                        Func<double?, double?, double?> function;
                        switch (selectedOperator)
                        {
                            case Operator.Add:
                                function = (x, y) => x + y;
                                break;
                            case Operator.Subtract:
                                function = (x, y) => x - y;
                                break;
                            case Operator.Multiply:
                                function = (x, y) => x * y;
                                break;
                            case Operator.Divide:
                                function = (x, y) => x / y;
                                break;
                            default:
                                throw new NotSupportedException("Unknown enumeration value " + selectedOperator + ".");
                        }

                        double operand1Value;
                        double.TryParse(operand1, out operand1Value);
                        double operand2Value;
                        double.TryParse(operand2, out operand2Value);
                        double? r = function(operand1Value, operand2Value);
                        return r == null ? null : r.ToString();
                    });
        }
 /// <summary>
 ///     Returns the store value generation strategy to set for the given property.
 /// </summary>
 /// <param name="property"> The property. </param>
 /// <param name="storeObject"> The identifier of the store object. </param>
 /// <returns> The new store value generation strategy to set for the given property. </returns>
 public static ValueGenerated?GetValueGenerated(IReadOnlyProperty property, in StoreObjectIdentifier storeObject)
예제 #26
0
 /// <summary>
 ///     Returns the name to use for the hi-lo sequence.
 /// </summary>
 /// <param name="property"> The property. </param>
 /// <param name="storeObject"> The identifier of the store object. </param>
 /// <returns> The name to use for the hi-lo sequence. </returns>
 public static string?GetHiLoSequenceName(this IReadOnlyProperty property, in StoreObjectIdentifier storeObject)
예제 #27
0
 /// <summary>
 /// Returns the name to use for the hi-lo sequence.
 /// </summary>
 /// <param name="property"> The property.</param>
 /// <returns>The name to use for the hi-lo sequence.</returns>
 public static string?GetHiLoSequenceName(this IReadOnlyProperty property)
 => (string?)property[NpgsqlAnnotationNames.HiLoSequenceName];
예제 #28
0
 public static CoreTypeMapping?FindTypeMapping([NotNull] this IReadOnlyProperty property)
 => ((Property)property).TypeMapping;
예제 #29
0
 /// <summary>
 ///     Returns the store value generation strategy to set for the given property.
 /// </summary>
 /// <param name="property"> The property. </param>
 /// <returns> The store value generation strategy to set for the given property. </returns>
 public static ValueGenerated?GetValueGenerated(IReadOnlyProperty property)
 => !property.GetContainingForeignKeys().Any(fk => !fk.IsBaseLinking()) &&
 ShouldHaveGeneratedProperty(property.FindContainingPrimaryKey()) &&
 CanBeGenerated(property)
             ? ValueGenerated.OnAdd
             : (ValueGenerated?)null;
예제 #30
0
 /// <summary>
 ///     Returns the SRID to use when creating a column for this property.
 /// </summary>
 /// <param name="property">The property.</param>
 /// <returns>The SRID to use when creating a column for this property.</returns>
 public static int?GetSrid(this IReadOnlyProperty property)
 => (int?)property[SqliteAnnotationNames.Srid];
예제 #31
0
 /// <summary>
 ///     Returns the property name that the property is mapped to when targeting Cosmos.
 /// </summary>
 /// <param name="property"> The property. </param>
 /// <returns> Returns the property name that the property is mapped to when targeting Cosmos. </returns>
 public static string GetJsonPropertyName(this IReadOnlyProperty property)
 => (string?)property[CosmosAnnotationNames.PropertyName]
 ?? GetDefaultJsonPropertyName(property);
예제 #32
0
 /// <summary>
 ///     Returns the SRID to use when creating a column for this property.
 /// </summary>
 /// <param name="property">The property.</param>
 /// <param name="storeObject">The identifier of the store object.</param>
 /// <returns>The SRID to use when creating a column for this property.</returns>
 public static int?GetSrid(
     this IReadOnlyProperty property,
     in StoreObjectIdentifier storeObject)