public virtual void Detects_incompatible_non_clustered_shared_key()
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <A>().HasOne <B>().WithOne().IsRequired().HasForeignKey <A>(a => a.Id).HasPrincipalKey <B>(b => b.Id);

            modelBuilder.Entity <A>().ToTable("Table")
            .HasKey(a => a.Id).IsClustered();
            modelBuilder.Entity <B>().ToTable("Table")
            .HasKey(b => b.Id).IsClustered(false);

            VerifyError(
                SqlServerStrings.DuplicateKeyMismatchedClustering("{'Id'}", nameof(B), "{'Id'}", nameof(A), "Table", "PK_Table"),
                modelBuilder.Model);
        }
        public void Throws_for_naked_type_name_on_property(string typeName)
        {
            var builder = CreateModelBuilder();

            var property = builder.Entity <StringCheese>()
                           .Property(e => e.StringWithSize)
                           .HasColumnType(typeName)
                           .Metadata;

            var mapper = CreateTypeMapper();

            Assert.Equal(
                SqlServerStrings.UnqualifiedDataTypeOnProperty(typeName, nameof(StringCheese.StringWithSize)),
                Assert.Throws <ArgumentException>(() => mapper.FindMapping(property)).Message, ignoreCase: true);
        }
    public virtual async Task Temporal_owned_range_operation_negative(bool async)
    {
        var contextFactory = await InitializeAsync <MyContext26451>();

        using (var context = contextFactory.CreateContext())
        {
            var message = async
                ? (await Assert.ThrowsAsync <InvalidOperationException>(
                       () => context.MainEntitiesDifferentTable.TemporalAll().ToListAsync())).Message
                : Assert.Throws <InvalidOperationException>(() => context.MainEntitiesDifferentTable.TemporalAll().ToList()).Message;

            Assert.Equal(
                SqlServerStrings.TemporalNavigationExpansionOnlySupportedForAsOf("AsOf"),
                message);
        }
    }
Exemple #4
0
        public void Throws_setting_sequence_generation_for_invalid_type()
        {
            var propertyBuilder = CreateBuilder()
                                  .Entity(typeof(Splot))
                                  .Property(typeof(string), "Name");

            Assert.Equal(
                SqlServerStrings.SequenceBadType("Name", nameof(Splot), "string"),
                Assert.Throws <ArgumentException>(
                    () => propertyBuilder.HasValueGenerationStrategy(SqlServerValueGenerationStrategy.SequenceHiLo)).Message);

            Assert.Equal(
                SqlServerStrings.SequenceBadType("Name", nameof(Splot), "string"),
                Assert.Throws <ArgumentException>(
                    () => new PropertyBuilder((IMutableProperty)propertyBuilder.Metadata).UseHiLo()).Message);
        }
        public void Temporal_period_property_must_non_nullable_datetime()
        {
            var modelBuilder1 = CreateConventionalModelBuilder();

            modelBuilder1.Entity <Dog>().Property(typeof(DateTime?), "Start");
            modelBuilder1.Entity <Dog>().ToTable(tb => tb.IsTemporal(ttb => ttb.HasPeriodStart("Start")));

            VerifyError(SqlServerStrings.TemporalPeriodPropertyMustBeNonNullableDateTime(nameof(Dog), "Start", nameof(DateTime)), modelBuilder1);

            var modelBuilder2 = CreateConventionalModelBuilder();

            modelBuilder2.Entity <Dog>().Property(typeof(int), "Start");
            modelBuilder2.Entity <Dog>().ToTable(tb => tb.IsTemporal(ttb => ttb.HasPeriodStart("Start")));

            VerifyError(SqlServerStrings.TemporalPeriodPropertyMustBeNonNullableDateTime(nameof(Dog), "Start", nameof(DateTime)), modelBuilder2);
        }
Exemple #6
0
        public void Throws_setting_identity_generation_for_invalid_type_only_with_explicit()
        {
            var propertyBuilder = CreateBuilder()
                                  .Entity(typeof(Splot))
                                  .Property(typeof(string), "Name");

            Assert.Equal(
                SqlServerStrings.IdentityBadType("Name", nameof(Splot), "string"),
                Assert.Throws <ArgumentException>(
                    () => propertyBuilder.HasValueGenerationStrategy(SqlServerValueGenerationStrategy.IdentityColumn)).Message);

            Assert.Equal(
                SqlServerStrings.IdentityBadType("Name", nameof(Splot), "string"),
                Assert.Throws <ArgumentException>(
                    () => new PropertyBuilder((IMutableProperty)propertyBuilder.Metadata).UseIdentityColumn()).Message);
        }
        public virtual void Detects_duplicate_index_names_within_hierarchy_with_different_different_include()
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <Animal>();
            modelBuilder.Entity <Cat>().HasIndex(c => c.Name).HasDatabaseName("IX_Animal_Name");
            modelBuilder.Entity <Dog>().HasIndex(d => d.Name).HasDatabaseName("IX_Animal_Name").IncludeProperties(nameof(Dog.Identity));

            VerifyError(
                SqlServerStrings.DuplicateIndexIncludedMismatch(
                    "{'" + nameof(Dog.Name) + "'}", nameof(Dog),
                    "{'" + nameof(Cat.Name) + "'}", nameof(Cat),
                    nameof(Animal), "IX_Animal_Name",
                    "{'Dog_Identity'}", "{}"),
                modelBuilder.Model);
        }
Exemple #8
0
        public void Throws_setting_sequence_generation_for_invalid_type_only_with_explicit()
        {
            var propertyBuilder = CreateBuilder()
                                  .Entity(typeof(Splot), ConfigurationSource.Convention)
                                  .Property("Name", typeof(string), ConfigurationSource.Convention);

            Assert.False(
                propertyBuilder.SqlServer(ConfigurationSource.Convention)
                .ValueGenerationStrategy(SqlServerValueGenerationStrategy.SequenceHiLo));

            Assert.Equal(
                SqlServerStrings.SequenceBadType("Name", nameof(Splot), "string"),
                Assert.Throws <ArgumentException>(
                    () => propertyBuilder.SqlServer(ConfigurationSource.Explicit)
                    .ValueGenerationStrategy(SqlServerValueGenerationStrategy.SequenceHiLo)).Message);
        }
Exemple #9
0
        public void Detects_non_key_SequenceHiLo(bool obsolete)
        {
            var modelBuilder = CreateConventionalModelBuilder();

            if (obsolete)
            {
#pragma warning disable 618
                modelBuilder.Entity <Dog>().Property(c => c.Type).ForSqlServerUseSequenceHiLo();
#pragma warning restore 618
            }
            else
            {
                modelBuilder.Entity <Dog>().Property(c => c.Type).UseHiLo();
            }

            VerifyError(SqlServerStrings.NonKeyValueGeneration(nameof(Dog.Type), nameof(Dog)), modelBuilder.Model);
        }
        public void Detects_indexed_include_properties(bool obsolete)
        {
            var modelBuilder = CreateConventionalModelBuilder();
            modelBuilder.Entity<Dog>().Property(c => c.Type);
            if (obsolete)
            {
#pragma warning disable 618
                modelBuilder.Entity<Dog>().HasIndex(nameof(Dog.Name)).ForSqlServerInclude(nameof(Dog.Name));
#pragma warning restore 618
            }
            else
            {
                modelBuilder.Entity<Dog>().HasIndex(nameof(Dog.Name)).IncludeProperties(nameof(Dog.Name));
            }

            VerifyError(SqlServerStrings.IncludePropertyInIndex(nameof(Dog), nameof(Dog.Name)), modelBuilder.Model);
        }
        protected virtual bool SetValueGenerationStrategy(SqlServerValueGenerationStrategy?value)
        {
            if (value != null)
            {
                var propertyType = Property.ClrType;

                if (value == SqlServerValueGenerationStrategy.IdentityColumn &&
                    !IsCompatibleIdentityColumn(propertyType))
                {
                    if (ShouldThrowOnInvalidConfiguration)
                    {
                        throw new ArgumentException(SqlServerStrings.IdentityBadType(
                                                        Property.Name, Property.DeclaringEntityType.DisplayName(), propertyType.ShortDisplayName()));
                    }

                    return(false);
                }

                if (value == SqlServerValueGenerationStrategy.SequenceHiLo &&
                    !IsCompatibleSequenceHiLo(propertyType))
                {
                    if (ShouldThrowOnInvalidConfiguration)
                    {
                        throw new ArgumentException(SqlServerStrings.SequenceBadType(
                                                        Property.Name, Property.DeclaringEntityType.DisplayName(), propertyType.ShortDisplayName()));
                    }

                    return(false);
                }
            }

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

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

            return(Annotations.SetAnnotation(SqlServerFullAnnotationNames.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>
        protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
        {
            var mapping = FindRawMapping(mappingInfo);

            if (mapping == null)
            {
                return(null);
            }

            mapping = mapping.CloneWithFacetedName(mappingInfo);

            if (_disallowedMappings.Contains(mapping.StoreType))
            {
                throw new ArgumentException(SqlServerStrings.UnqualifiedDataType(mapping.StoreType));
            }

            return(mapping);
        }
    /// <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 override void ValidateQueryRootCreation(IEntityType entityType, QueryRootExpression?source)
    {
        if (source is TemporalQueryRootExpression)
        {
            if (!entityType.GetRootType().IsTemporal())
            {
                throw new InvalidOperationException(
                          SqlServerStrings.TemporalNavigationExpansionBetweenTemporalAndNonTemporal(entityType.DisplayName()));
            }

            if (source is not TemporalAsOfQueryRootExpression)
            {
                throw new InvalidOperationException(
                          SqlServerStrings.TemporalNavigationExpansionOnlySupportedForAsOf("AsOf"));
            }
        }

        base.ValidateQueryRootCreation(entityType, source);
    }
 /// <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,
     [NotNull] IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
 {
     foreach (var entityType in model.GetEntityTypes())
     {
         foreach (var property in entityType.GetDeclaredProperties()
                  .Where(
                      p => p.GetValueGenerationStrategy() == SqlServerValueGenerationStrategy.SequenceHiLo &&
                      ((IConventionProperty)p).GetValueGenerationStrategyConfigurationSource() != null &&
                      !p.IsKey() &&
                      p.ValueGenerated != ValueGenerated.Never &&
                      (!(p.FindAnnotation(SqlServerAnnotationNames.ValueGenerationStrategy) is IConventionAnnotation strategy) ||
                       !ConfigurationSource.Convention.Overrides(strategy.GetConfigurationSource()))))
         {
             throw new InvalidOperationException(
                       SqlServerStrings.NonKeyValueGeneration(property.Name, property.DeclaringEntityType.DisplayName()));
         }
     }
 }
        public void Detects_multiple_identity_properties(bool obsolete)
        {
            var modelBuilder = CreateConventionalModelBuilder();
            modelBuilder.Entity<Dog>().Property(d => d.Id).ValueGeneratedNever();

            if (obsolete)
            {
#pragma warning disable 618
                modelBuilder.Entity<Dog>().Property(c => c.Type).UseSqlServerIdentityColumn();
                modelBuilder.Entity<Dog>().Property<int?>("Tag").UseSqlServerIdentityColumn();
#pragma warning restore 618
            }
            else
            {
                modelBuilder.Entity<Dog>().Property(c => c.Type).UseIdentityColumn();
                modelBuilder.Entity<Dog>().Property<int?>("Tag").UseIdentityColumn();
            }

            VerifyError(SqlServerStrings.MultipleIdentityColumns("'Dog.Tag', 'Dog.Type'", nameof(Dog)), modelBuilder.Model);
        }
Exemple #16
0
        public virtual void Detects_duplicate_column_names_within_hierarchy_with_different_value_generation_strategy()
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <Animal>();
            modelBuilder.Entity <Cat>(cb =>
            {
                cb.Property(c => c.Identity).UseSqlServerIdentityColumn();
                cb.Property(c => c.Identity).HasColumnName(nameof(Cat.Identity));
            });
            modelBuilder.Entity <Dog>(db =>
            {
                db.Property(d => d.Identity).ValueGeneratedNever();
                db.Property(c => c.Identity).HasColumnName(nameof(Dog.Identity));
            });

            VerifyError(
                SqlServerStrings.DuplicateColumnNameValueGenerationStrategyMismatch(
                    nameof(Cat), nameof(Cat.Identity), nameof(Dog), nameof(Dog.Identity), nameof(Cat.Identity), nameof(Animal)), modelBuilder.Model);
        }
        /// <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 ValidateIndexIncludeProperties(
            [NotNull] IModel model,
            [NotNull] IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
        {
            foreach (var index in model.GetEntityTypes().SelectMany(t => t.GetDeclaredIndexes()))
            {
                var includeProperties = index.GetIncludeProperties();
                if (includeProperties?.Count > 0)
                {
                    var notFound = includeProperties
                                   .FirstOrDefault(i => index.DeclaringEntityType.FindProperty(i) == null);

                    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
                                  .FirstOrDefault(i => index.Properties.Any(p => i == p.Name));

                    if (inIndex != null)
                    {
                        throw new InvalidOperationException(
                                  SqlServerStrings.IncludePropertyInIndex(index.DeclaringEntityType.DisplayName(), inIndex));
                    }
                }
            }
        }
        /// <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 override QueryRootExpression CreateQueryRoot(IEntityType entityType, QueryRootExpression?source)
        {
            if (source is TemporalQueryRootExpression)
            {
                if (!entityType.GetRootType().IsTemporal())
                {
                    throw new InvalidOperationException(SqlServerStrings.TemporalNavigationExpansionBetweenTemporalAndNonTemporal(entityType.DisplayName()));
                }

                if (source is TemporalAsOfQueryRootExpression asOf)
                {
                    return(source.QueryProvider != null
                        ? new TemporalAsOfQueryRootExpression(source.QueryProvider, entityType, asOf.PointInTime)
                        : new TemporalAsOfQueryRootExpression(entityType, asOf.PointInTime));
                }

                throw new InvalidOperationException(SqlServerStrings.TemporalNavigationExpansionOnlySupportedForAsOf("AsOf"));
            }

            return(base.CreateQueryRoot(entityType, source));
        }
        public virtual void Detects_duplicate_column_names_within_hierarchy_with_different_identity_increment()
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <Animal>();
            modelBuilder.Entity <Cat>(
                cb =>
            {
                cb.Property(c => c.Identity).UseIdentityColumn().HasColumnName(nameof(Cat.Identity));
            });
            modelBuilder.Entity <Dog>(
                db =>
            {
                db.Property(d => d.Identity).UseIdentityColumn(increment: 2).HasColumnName(nameof(Dog.Identity));
            });

            VerifyError(
                SqlServerStrings.DuplicateColumnIdentityIncrementMismatch(
                    nameof(Cat), nameof(Cat.Identity), nameof(Dog), nameof(Dog.Identity), nameof(Cat.Identity), nameof(Animal)),
                modelBuilder.Model);
        }
Exemple #20
0
        public virtual void Detects_incompatible_memory_optimized_shared_table(bool obsolete)
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <A>().HasOne <B>().WithOne().IsRequired().HasForeignKey <A>(a => a.Id).HasPrincipalKey <B>(b => b.Id);

            if (obsolete)
            {
#pragma warning disable 618
                modelBuilder.Entity <A>().ToTable("Table").ForSqlServerIsMemoryOptimized();
#pragma warning restore 618
            }
            else
            {
                modelBuilder.Entity <A>().ToTable("Table").IsMemoryOptimized();
            }
            modelBuilder.Entity <B>().ToTable("Table");

            VerifyError(
                SqlServerStrings.IncompatibleTableMemoryOptimizedMismatch("Table", nameof(A), nameof(B), nameof(A), nameof(B)),
                modelBuilder.Model);
        }
Exemple #21
0
        protected virtual bool SetValueGenerationStrategy(SqlServerValueGenerationStrategy?value)
        {
            if (value != null)
            {
                var propertyType = Property.ClrType;

                if (value == SqlServerValueGenerationStrategy.IdentityColumn &&
                    propertyType != typeof(decimal) &&
                    (!propertyType.IsInteger() ||
                     propertyType == typeof(byte) ||
                     propertyType == typeof(byte?)))
                {
                    throw new ArgumentException(SqlServerStrings.IdentityBadType(
                                                    Property.Name, Property.DeclaringEntityType.DisplayName(), propertyType.ShortDisplayName()));
                }

                if ((value == SqlServerValueGenerationStrategy.SequenceHiLo) &&
                    !propertyType.IsInteger())
                {
                    throw new ArgumentException(SqlServerStrings.SequenceBadType(
                                                    Property.Name, Property.DeclaringEntityType.DisplayName(), propertyType.ShortDisplayName()));
                }
            }

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

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

            return(Annotations.SetAnnotation(SqlServerFullAnnotationNames.Instance.ValueGenerationStrategy, null, value));
        }
        /// <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,
            string schema,
            IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
        {
            var firstMappedType   = mappedTypes[0];
            var isMemoryOptimized = firstMappedType.IsMemoryOptimized();

            foreach (var otherMappedType in mappedTypes.Skip(1))
            {
                if (isMemoryOptimized != otherMappedType.IsMemoryOptimized())
                {
                    throw new InvalidOperationException(
                              SqlServerStrings.IncompatibleTableMemoryOptimizedMismatch(
                                  tableName, firstMappedType.DisplayName(), otherMappedType.DisplayName(),
                                  isMemoryOptimized ? firstMappedType.DisplayName() : otherMappedType.DisplayName(),
                                  !isMemoryOptimized ? firstMappedType.DisplayName() : otherMappedType.DisplayName()));
                }
            }

            base.ValidateSharedTableCompatibility(mappedTypes, tableName, schema, logger);
        }
    public virtual void Detects_duplicate_column_names_within_hierarchy_with_different_sparseness()
    {
        var modelBuilder = CreateConventionalModelBuilder();

        modelBuilder.Entity <Animal>();
        modelBuilder.Entity <Cat>(
            cb =>
        {
            cb.ToTable("Animal");
            cb.Property(c => c.Breed).HasColumnName(nameof(Cat.Breed)).IsSparse();
        });
        modelBuilder.Entity <Dog>(
            db =>
        {
            db.ToTable("Animal");
            db.Property(d => d.Breed).HasColumnName(nameof(Dog.Breed));
        });

        VerifyError(
            SqlServerStrings.DuplicateColumnSparsenessMismatch(
                nameof(Cat), nameof(Cat.Breed), nameof(Dog), nameof(Dog.Breed), nameof(Cat.Breed), nameof(Animal)),
            modelBuilder);
    }
        public virtual void Detects_duplicate_column_name_with_different_HiLoSequence_schema()
        {
            var modelBuilder = CreateConventionalModelBuilder();

            modelBuilder.Entity <Cat>(
                cb =>
            {
                cb.ToTable("Animal");
                cb.Property(c => c.Id).UseHiLo("foo", "dbo");
            });
            modelBuilder.Entity <Dog>(
                db =>
            {
                db.ToTable("Animal");
                db.Property(d => d.Id).UseHiLo("foo", "dba");
                db.HasOne <Cat>().WithOne().HasForeignKey <Dog>(d => d.Id);
            });

            VerifyError(
                SqlServerStrings.DuplicateColumnSequenceMismatch(
                    nameof(Cat), nameof(Cat.Id), nameof(Dog), nameof(Dog.Id), nameof(Cat.Id), nameof(Animal)),
                modelBuilder.Model);
        }
Exemple #25
0
        private static void CheckValueGenerationStrategy(IProperty property, SqlServerValueGenerationStrategy?value)
        {
            if (value != null)
            {
                var propertyType = property.ClrType;

                if (value == SqlServerValueGenerationStrategy.IdentityColumn &&
                    !IsCompatibleWithValueGeneration(property))
                {
                    throw new ArgumentException(
                              SqlServerStrings.IdentityBadType(
                                  property.Name, property.DeclaringEntityType.DisplayName(), propertyType.ShortDisplayName()));
                }

                if (value == SqlServerValueGenerationStrategy.SequenceHiLo &&
                    !IsCompatibleWithValueGeneration(property))
                {
                    throw new ArgumentException(
                              SqlServerStrings.SequenceBadType(
                                  property.Name, property.DeclaringEntityType.DisplayName(), propertyType.ShortDisplayName()));
                }
            }
        }
Exemple #26
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 ValidateTemporalTables(
        IModel model,
        IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
    {
        var temporalEntityTypes = model.GetEntityTypes().Where(t => t.IsTemporal()).ToList();

        foreach (var temporalEntityType in temporalEntityTypes)
        {
            if (temporalEntityType.BaseType != null)
            {
                throw new InvalidOperationException(SqlServerStrings.TemporalOnlyOnRoot(temporalEntityType.DisplayName()));
            }

            ValidateTemporalPeriodProperty(temporalEntityType, periodStart: true);
            ValidateTemporalPeriodProperty(temporalEntityType, periodStart: false);

            var derivedTableMappings = temporalEntityType.GetDerivedTypes().Select(t => t.GetTableName()).Distinct().ToList();
            if (derivedTableMappings.Count > 0 &&
                (derivedTableMappings.Count != 1 || derivedTableMappings.First() != temporalEntityType.GetTableName()))
            {
                throw new InvalidOperationException(SqlServerStrings.TemporalOnlySupportedForTPH(temporalEntityType.DisplayName()));
            }
        }
    }
Exemple #27
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,
        string?schema,
        IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
    {
        var firstMappedType   = mappedTypes[0];
        var isMemoryOptimized = firstMappedType.IsMemoryOptimized();

        foreach (var otherMappedType in mappedTypes.Skip(1))
        {
            if (isMemoryOptimized != otherMappedType.IsMemoryOptimized())
            {
                throw new InvalidOperationException(
                          SqlServerStrings.IncompatibleTableMemoryOptimizedMismatch(
                              tableName, firstMappedType.DisplayName(), otherMappedType.DisplayName(),
                              isMemoryOptimized ? firstMappedType.DisplayName() : otherMappedType.DisplayName(),
                              !isMemoryOptimized ? firstMappedType.DisplayName() : otherMappedType.DisplayName()));
            }
        }

        if (mappedTypes.Any(t => t.IsTemporal()) &&
            mappedTypes.Select(t => t.GetRootType()).Distinct().Count() > 1)
        {
            // table splitting is only supported when all entites mapped to this table
            // have consistent temporal period mappings also
            var expectedPeriodStartColumnName = default(string);
            var expectedPeriodEndColumnName   = default(string);

            foreach (var mappedType in mappedTypes.Where(t => t.BaseType == null))
            {
                if (!mappedType.IsTemporal())
                {
                    throw new InvalidOperationException(
                              SqlServerStrings.TemporalAllEntitiesMappedToSameTableMustBeTemporal(
                                  mappedType.DisplayName()));
                }

                var periodStartPropertyName = mappedType.GetPeriodStartPropertyName();
                var periodEndPropertyName   = mappedType.GetPeriodEndPropertyName();

                var periodStartProperty = mappedType.GetProperty(periodStartPropertyName !);
                var periodEndProperty   = mappedType.GetProperty(periodEndPropertyName !);

                var storeObjectIdentifier = StoreObjectIdentifier.Table(tableName, mappedType.GetSchema());
                var periodStartColumnName = periodStartProperty.GetColumnName(storeObjectIdentifier);
                var periodEndColumnName   = periodEndProperty.GetColumnName(storeObjectIdentifier);

                if (expectedPeriodStartColumnName == null)
                {
                    expectedPeriodStartColumnName = periodStartColumnName;
                }
                else if (expectedPeriodStartColumnName != periodStartColumnName)
                {
                    throw new InvalidOperationException(
                              SqlServerStrings.TemporalNotSupportedForTableSplittingWithInconsistentPeriodMapping(
                                  "start",
                                  mappedType.DisplayName(),
                                  periodStartPropertyName,
                                  periodStartColumnName,
                                  expectedPeriodStartColumnName));
                }

                if (expectedPeriodEndColumnName == null)
                {
                    expectedPeriodEndColumnName = periodEndColumnName;
                }
                else if (expectedPeriodEndColumnName != periodEndColumnName)
                {
                    throw new InvalidOperationException(
                              SqlServerStrings.TemporalNotSupportedForTableSplittingWithInconsistentPeriodMapping(
                                  "end",
                                  mappedType.DisplayName(),
                                  periodEndPropertyName,
                                  periodEndColumnName,
                                  expectedPeriodEndColumnName));
                }
            }
        }

        base.ValidateSharedTableCompatibility(mappedTypes, tableName, schema, logger);
    }
 private static bool ContainsCore(string propertyName, string searchCondition, int?languageTerm)
 {
     throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(Contains)));
 }
 /// <summary>
 ///     Validate if the given string is a valid date.
 ///     Corresponds to the SQL Server's ISDATE('date').
 /// </summary>
 /// <param name="_">The DbFunctions instance.</param>
 /// <param name="expression">Expression to validate</param>
 /// <returns>true for valid date and false otherwise.</returns>
 public static bool IsDate(
     [CanBeNull] this DbFunctions _,
     [NotNull] string expression)
 => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(IsDate)));
 private static bool FreeTextCore(string propertyName, string freeText, int?languageTerm)
 {
     throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(FreeText)));
 }