Ejemplo n.º 1
0
        public virtual void Detects_missing_discriminator()
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <Customer>().ToContainer("Orders").HasNoDiscriminator();
            modelBuilder.Entity <Order>().ToContainer("Orders");

            VerifyError(CosmosStrings.NoDiscriminatorProperty(typeof(Customer).Name, "Orders"), modelBuilder);
        }
        /// <summary>
        ///     Validates the compatibility of entity types sharing a given container.
        /// </summary>
        /// <param name="mappedTypes"> The mapped entity types. </param>
        /// <param name="containerName"> The container name. </param>
        /// <param name="logger"> The logger to use. </param>
        protected virtual void ValidateSharedContainerCompatibility(
            [NotNull] IReadOnlyList <IEntityType> mappedTypes,
            [NotNull] string containerName,
            [NotNull] IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
        {
            if (mappedTypes.Count == 1)
            {
                var entityType = mappedTypes[0];
                var partitionKeyPropertyName = entityType.GetCosmosPartitionKeyPropertyName();
                if (partitionKeyPropertyName != null)
                {
                    var nextPartitionKeyProperty = entityType.FindProperty(partitionKeyPropertyName);
                    if (nextPartitionKeyProperty == null)
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.PartitionKeyMissingProperty(entityType.DisplayName(), partitionKeyPropertyName));
                    }
                }
                return;
            }

            var         discriminatorValues = new Dictionary <object, IEntityType>();
            IProperty   partitionKey        = null;
            IEntityType firstEntityType     = null;

            foreach (var entityType in mappedTypes)
            {
                var partitionKeyPropertyName = entityType.GetCosmosPartitionKeyPropertyName();
                if (partitionKeyPropertyName != null)
                {
                    var nextPartitionKeyProperty = entityType.FindProperty(partitionKeyPropertyName);
                    if (nextPartitionKeyProperty == null)
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.PartitionKeyMissingProperty(entityType.DisplayName(), partitionKeyPropertyName));
                    }

                    if (partitionKey == null)
                    {
                        if (firstEntityType != null)
                        {
                            throw new InvalidOperationException(CosmosStrings.NoPartitionKey(firstEntityType.DisplayName(), containerName));
                        }
                        partitionKey = nextPartitionKeyProperty;
                    }
                    else if (partitionKey.GetCosmosPropertyName() != nextPartitionKeyProperty.GetCosmosPropertyName())
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.PartitionKeyStoreNameMismatch(
                                      partitionKey.Name, firstEntityType.DisplayName(), partitionKey.GetCosmosPropertyName(),
                                      nextPartitionKeyProperty.Name, entityType.DisplayName(), nextPartitionKeyProperty.GetCosmosPropertyName()));
                    }
                    else if ((partitionKey.GetTypeMapping().Converter?.ProviderClrType ?? partitionKey.ClrType)
                             != (nextPartitionKeyProperty.GetTypeMapping().Converter?.ProviderClrType ?? nextPartitionKeyProperty.ClrType))
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.PartitionKeyStoreTypeMismatch(
                                      partitionKey.Name,
                                      firstEntityType.DisplayName(),
                                      (partitionKey.GetTypeMapping().Converter?.ProviderClrType ?? partitionKey.ClrType).ShortDisplayName(),
                                      nextPartitionKeyProperty.Name,
                                      entityType.DisplayName(),
                                      (nextPartitionKeyProperty.GetTypeMapping().Converter?.ProviderClrType ?? nextPartitionKeyProperty.ClrType)
                                      .ShortDisplayName()));
                    }
                }
                else if (partitionKey != null)
                {
                    throw new InvalidOperationException(CosmosStrings.NoPartitionKey(entityType.DisplayName(), containerName));
                }

                if (firstEntityType == null)
                {
                    firstEntityType = entityType;
                }

                if (entityType.ClrType?.IsInstantiable() == true)
                {
                    if (entityType.GetDiscriminatorProperty() == null)
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.NoDiscriminatorProperty(entityType.DisplayName(), containerName));
                    }

                    var discriminatorValue = entityType.GetDiscriminatorValue();
                    if (discriminatorValue == null)
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.NoDiscriminatorValue(entityType.DisplayName(), containerName));
                    }

                    if (discriminatorValues.TryGetValue(discriminatorValue, out var duplicateEntityType))
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.DuplicateDiscriminatorValue(
                                      entityType.DisplayName(), discriminatorValue, duplicateEntityType.DisplayName(), containerName));
                    }

                    discriminatorValues[discriminatorValue] = entityType;
                }
            }
        }
Ejemplo n.º 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>
        protected virtual void ValidateSharedContainerCompatibility(
            [NotNull] IReadOnlyList <IEntityType> mappedTypes,
            [NotNull] string container,
            [NotNull] IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
        {
            var         discriminatorValues = new Dictionary <object, IEntityType>();
            IProperty   partitionKey        = null;
            IEntityType firstEntityType     = null;

            foreach (var entityType in mappedTypes)
            {
                Check.DebugAssert(entityType.IsDocumentRoot(), "Only document roots expected here.");
                var partitionKeyPropertyName = entityType.GetPartitionKeyPropertyName();
                if (partitionKeyPropertyName != null)
                {
                    var nextPartitionKeyProperty = entityType.FindProperty(partitionKeyPropertyName);
                    if (partitionKey == null)
                    {
                        if (firstEntityType != null)
                        {
                            throw new InvalidOperationException(CosmosStrings.NoPartitionKey(firstEntityType.DisplayName(), container));
                        }

                        partitionKey = nextPartitionKeyProperty;
                    }
                    else if (partitionKey.GetJsonPropertyName() != nextPartitionKeyProperty.GetJsonPropertyName())
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.PartitionKeyStoreNameMismatch(
                                      partitionKey.Name, firstEntityType.DisplayName(), partitionKey.GetJsonPropertyName(),
                                      nextPartitionKeyProperty.Name, entityType.DisplayName(), nextPartitionKeyProperty.GetJsonPropertyName()));
                    }
                }
                else if (partitionKey != null)
                {
                    throw new InvalidOperationException(CosmosStrings.NoPartitionKey(entityType.DisplayName(), container));
                }

                if (mappedTypes.Count == 1)
                {
                    break;
                }

                if (firstEntityType == null)
                {
                    firstEntityType = entityType;
                }

                if (entityType.ClrType.IsInstantiable() &&
                    entityType.GetContainingPropertyName() == null)
                {
                    if (entityType.GetDiscriminatorProperty() == null)
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.NoDiscriminatorProperty(entityType.DisplayName(), container));
                    }

                    var discriminatorValue = entityType.GetDiscriminatorValue();
                    if (discriminatorValue == null)
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.NoDiscriminatorValue(entityType.DisplayName(), container));
                    }

                    if (discriminatorValues.TryGetValue(discriminatorValue, out var duplicateEntityType))
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.DuplicateDiscriminatorValue(
                                      entityType.DisplayName(), discriminatorValue, duplicateEntityType.DisplayName(), container));
                    }

                    discriminatorValues[discriminatorValue] = entityType;
                }
            }
        }
Ejemplo n.º 4
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 ValidateSharedContainerCompatibility(
            IReadOnlyList <IEntityType> mappedTypes,
            string container,
            IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
        {
            var                  discriminatorValues = new Dictionary <object, IEntityType>();
            IProperty?           partitionKey        = null;
            int?                 analyticalTTL       = null;
            int?                 defaultTTL          = null;
            ThroughputProperties?throughput          = null;
            IEntityType?         firstEntityType     = null;

            foreach (var entityType in mappedTypes)
            {
                Check.DebugAssert(entityType.IsDocumentRoot(), "Only document roots expected here.");
                var partitionKeyPropertyName = entityType.GetPartitionKeyPropertyName();
                if (partitionKeyPropertyName != null)
                {
                    var nextPartitionKeyProperty = entityType.FindProperty(partitionKeyPropertyName) !;
                    if (partitionKey == null)
                    {
                        if (firstEntityType != null)
                        {
                            throw new InvalidOperationException(CosmosStrings.NoPartitionKey(firstEntityType.DisplayName(), container));
                        }

                        partitionKey = nextPartitionKeyProperty;
                    }
                    else if (partitionKey.GetJsonPropertyName() != nextPartitionKeyProperty.GetJsonPropertyName())
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.PartitionKeyStoreNameMismatch(
                                      partitionKey.Name, firstEntityType !.DisplayName(), partitionKey.GetJsonPropertyName(),
                                      nextPartitionKeyProperty.Name, entityType.DisplayName(), nextPartitionKeyProperty.GetJsonPropertyName()));
                    }
                }
                else if (partitionKey != null)
                {
                    throw new InvalidOperationException(CosmosStrings.NoPartitionKey(entityType.DisplayName(), container));
                }

                if (mappedTypes.Count == 1)
                {
                    break;
                }

                if (firstEntityType == null)
                {
                    firstEntityType = entityType;
                }

                if (entityType.ClrType.IsInstantiable() &&
                    entityType.GetContainingPropertyName() == null)
                {
                    if (entityType.FindDiscriminatorProperty() == null)
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.NoDiscriminatorProperty(entityType.DisplayName(), container));
                    }

                    var discriminatorValue = entityType.GetDiscriminatorValue();
                    if (discriminatorValue == null)
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.NoDiscriminatorValue(entityType.DisplayName(), container));
                    }

                    if (discriminatorValues.TryGetValue(discriminatorValue, out var duplicateEntityType))
                    {
                        throw new InvalidOperationException(
                                  CosmosStrings.DuplicateDiscriminatorValue(
                                      entityType.DisplayName(), discriminatorValue, duplicateEntityType.DisplayName(), container));
                    }

                    discriminatorValues[discriminatorValue] = entityType;
                }

                var currentAnalyticalTTL = entityType.GetAnalyticalStoreTimeToLive();
                if (currentAnalyticalTTL != null)
                {
                    if (analyticalTTL == null)
                    {
                        analyticalTTL = currentAnalyticalTTL;
                    }
                    else if (analyticalTTL != currentAnalyticalTTL)
                    {
                        var conflictingEntityType = mappedTypes.First(et => et.GetAnalyticalStoreTimeToLive() != null);
                        throw new InvalidOperationException(
                                  CosmosStrings.AnalyticalTTLMismatch(
                                      analyticalTTL, conflictingEntityType.DisplayName(), entityType.DisplayName(), currentAnalyticalTTL,
                                      container));
                    }
                }

                var currentDefaultTTL = entityType.GetDefaultTimeToLive();
                if (currentDefaultTTL != null)
                {
                    if (defaultTTL == null)
                    {
                        defaultTTL = currentDefaultTTL;
                    }
                    else if (defaultTTL != currentDefaultTTL)
                    {
                        var conflictingEntityType = mappedTypes.First(et => et.GetDefaultTimeToLive() != null);
                        throw new InvalidOperationException(
                                  CosmosStrings.DefaultTTLMismatch(
                                      defaultTTL, conflictingEntityType.DisplayName(), entityType.DisplayName(), currentDefaultTTL, container));
                    }
                }

                var currentThroughput = entityType.GetThroughput();
                if (currentThroughput != null)
                {
                    if (throughput == null)
                    {
                        throughput = currentThroughput;
                    }
                    else if ((throughput.AutoscaleMaxThroughput ?? throughput.Throughput)
                             != (currentThroughput.AutoscaleMaxThroughput ?? currentThroughput.Throughput))
                    {
                        var conflictingEntityType = mappedTypes.First(et => et.GetThroughput() != null);
                        throw new InvalidOperationException(
                                  CosmosStrings.ThroughputMismatch(
                                      throughput.AutoscaleMaxThroughput ?? throughput.Throughput, conflictingEntityType.DisplayName(),
                                      entityType.DisplayName(), currentThroughput.AutoscaleMaxThroughput ?? currentThroughput.Throughput,
                                      container));
                    }
                    else if ((throughput.AutoscaleMaxThroughput == null)
                             != (currentThroughput.AutoscaleMaxThroughput == null))
                    {
                        var conflictingEntityType = mappedTypes.First(et => et.GetThroughput() != null);
                        var autoscaleType         = throughput.AutoscaleMaxThroughput == null
                            ? entityType
                            : conflictingEntityType;
                        var manualType = throughput.AutoscaleMaxThroughput != null
                            ? entityType
                            : conflictingEntityType;

                        throw new InvalidOperationException(
                                  CosmosStrings.ThroughputTypeMismatch(
                                      manualType.DisplayName(), autoscaleType.DisplayName(), container));
                    }
                }
            }
        }