/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected override void ValidateSharedKeysCompatibility( IReadOnlyList <IEntityType> mappedTypes, string tableName) { base.ValidateSharedKeysCompatibility(mappedTypes, tableName); var keyMappings = new Dictionary <string, IKey>(); foreach (var key in mappedTypes.SelectMany(et => et.GetDeclaredKeys())) { var keyName = key.Relational().Name; if (!keyMappings.TryGetValue(keyName, out var duplicateKey)) { keyMappings[keyName] = key; continue; } if (key.MySql().IsClustered != duplicateKey.MySql().IsClustered) { throw new InvalidOperationException( MySqlStrings.DuplicateKeyMismatchedClustering( Property.Format(key.Properties), key.DeclaringEntityType.DisplayName(), Property.Format(duplicateKey.Properties), duplicateKey.DeclaringEntityType.DisplayName(), tableName, keyName)); } } }
public virtual void Detects_incompatible_non_clustered_shared_key(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") .HasKey(a => a.Id).ForMySqlIsClustered(); modelBuilder.Entity <B>().ToTable("Table") .HasKey(b => b.Id).ForMySqlIsClustered(false); #pragma warning restore 618 } else { modelBuilder.Entity <A>().ToTable("Table") .HasKey(a => a.Id).IsClustered(); modelBuilder.Entity <B>().ToTable("Table") .HasKey(b => b.Id).IsClustered(false); } VerifyError( MySqlStrings.DuplicateKeyMismatchedClustering("{'Id'}", nameof(B), "{'Id'}", nameof(A), "Table", "PK_Table"), modelBuilder.Model); }
/// <summary> /// Returns the distance between g1 and g2, measured in the length unit of the spatial reference system /// (SRS) of the geometry arguments. /// For MySQL 8, this is equivalent of calling ST_Distance() when using an SRID of `0`. /// For MySQL < 8 and MariaDB, this is equivalent of calling ST_Distance() with any SRID. /// </summary> /// <param name="_">The DbFunctions instance.</param> /// <param name="g1">First geometry argument.</param> /// <param name="g2">Second geometry argument.</param> /// <returns>Distance betweeen g1 and g2.</returns> public static double SpatialDistancePlanar( [CanBeNull] this DbFunctions _, Geometry g1, Geometry g2) { throw new InvalidOperationException(MySqlStrings.FunctionOnClient(nameof(SpatialDistancePlanar))); }
public virtual void Detects_duplicate_column_names_within_hierarchy_with_different_value_generation_strategy(bool obsolete) { var modelBuilder = CreateConventionalModelBuilder(); modelBuilder.Entity <Animal>(); modelBuilder.Entity <Cat>( cb => { if (obsolete) { #pragma warning disable 618 cb.Property(c => c.Identity).UseMySqlIdentityColumn(); #pragma warning restore 618 } else { cb.Property(c => c.Identity).UseIdentityColumn(); } 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( MySqlStrings.DuplicateColumnNameValueGenerationStrategyMismatch( nameof(Cat), nameof(Cat.Identity), nameof(Dog), nameof(Dog.Identity), nameof(Cat.Identity), nameof(Animal)), modelBuilder.Model); }
public override Task Using_static_string_Equals_with_StringComparison_throws_informative_error(bool async) { return(AssertTranslationFailedWithDetails( () => AssertQuery( async, ss => ss.Set <Customer>().Where(c => string.Equals(c.CustomerID, "ALFKI", StringComparison.InvariantCulture))), MySqlStrings.QueryUnableToTranslateMethodWithStringComparison(nameof(String), nameof(string.Equals), nameof(MySqlDbContextOptionsBuilder.EnableStringComparisonTranslations)))); }
/// <summary> /// Returns the mimimum spherical distance between Point or MultiPoint arguments on a sphere in meters, /// by using the specified algorithm. /// It is assumed that `g1` and `g2` are associated with an SRID of `4326`. /// </summary> /// <param name="_">The DbFunctions instance.</param> /// <param name="g1">First geometry argument.</param> /// <param name="g2">Second geometry argument.</param> /// <param name="algorithm">The algorithm to use. Must be directly supplied as a constant.</param> /// <returns>Distance betweeen g1 and g2.</returns> public static double SpatialDistanceSphere( [CanBeNull] this DbFunctions _, Geometry g1, Geometry g2, SpatialDistanceAlgorithm algorithm) { throw new InvalidOperationException(MySqlStrings.FunctionOnClient(nameof(SpatialDistanceSphere))); }
public void Throws_for_non_key_SequenceHiLo() { var modelBuilder = CreateConventionalModelBuilder(); modelBuilder.Entity <Dog>().Property(c => c.Type).ForMySqlUseSequenceHiLo(); VerifyError(MySqlStrings.NonKeyValueGeneration(nameof(Dog.Type), nameof(Dog)), modelBuilder.Model); }
public void IsDate_should_throw_on_client_eval() { var exIsDate = Assert.Throws <InvalidOperationException>(() => EF.Functions.IsDate("#ISDATE#")); Assert.Equal( MySqlStrings.FunctionOnClient(nameof(MySqlDbFunctionsExtensions.IsDate)), exIsDate.Message); }
public void Throws_for_naked_type_name(string typeName) { var mapper = CreateTypeMapper(); Assert.Equal( MySqlStrings.UnqualifiedDataType(typeName), Assert.Throws <ArgumentException>(() => mapper.FindMapping(typeName)).Message); }
public void Throws_for_indexed_include_properties() { var modelBuilder = InMemoryTestHelpers.Instance.CreateConventionBuilder(); modelBuilder.Entity <Dog>().Property(c => c.Type); modelBuilder.Entity <Dog>().HasIndex(nameof(Dog.Name)).ForMySqlInclude(nameof(Dog.Name)); VerifyError(MySqlStrings.IncludePropertyInIndex(nameof(Dog), nameof(Dog.Name)), modelBuilder.Model); }
public void Throws_for_multiple_identity_properties() { var modelBuilder = InMemoryTestHelpers.Instance.CreateConventionBuilder(); modelBuilder.Entity <Dog>().Property(c => c.Type).UseMySqlIdentityColumn(); modelBuilder.Entity <Dog>().Property <int?>("Tag").UseMySqlIdentityColumn(); VerifyError(MySqlStrings.MultipleIdentityColumns("'Dog.Tag', 'Dog.Type'", nameof(Dog)), modelBuilder.Model); }
protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (NewArrayExpressionSupportMethodInfos.Contains(methodCallExpression.Method)) { var arguments = new Expression[methodCallExpression.Arguments.Count]; for (var i = 0; i < arguments.Length; i++) { var argument = methodCallExpression.Arguments[i]; if (argument is NewArrayExpression newArrayExpression) { if (TranslationFailed(argument, VisitMethodCallNewArray(newArrayExpression), out var sqlExpression)) { return(null); } arguments[i] = sqlExpression; } else { arguments[i] = argument; } } methodCallExpression = methodCallExpression.Update(methodCallExpression.Object, arguments); } var result = base.VisitMethodCall(methodCallExpression); if (result == null && MySqlStringComparisonMethodTranslator.StringComparisonMethodInfos.Any(m => m == methodCallExpression.Method)) { var message = MySqlStrings.QueryUnableToTranslateMethodWithStringComparison( methodCallExpression.Method.DeclaringType.Name, methodCallExpression.Method.Name, nameof(MySqlDbContextOptionsBuilder.EnableStringComparisonTranslations)); // EF Core returns an error message on its own, when the string.Equals() methods (static and non-static) are being used with // a `StringComparison` parameter. // Since we also support other translations, but all of them only when opted in, we will replace the EF Core error message // with our own, that is more appropriate for our case. if (TranslationErrorDetails.Contains(CoreStrings.QueryUnableToTranslateStringEqualsWithStringComparison)) { var translationErrorDetails = TranslationErrorDetails; ResetTranslationErrorDetails(); message = translationErrorDetails.Replace(CoreStrings.QueryUnableToTranslateStringEqualsWithStringComparison, message); } AddTranslationErrorDetails(message); } return(result); }
public virtual void Detects_incompatible_memory_optimized_shared_table() { 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").ForMySqlIsMemoryOptimized(); modelBuilder.Entity <B>().ToTable("Table"); VerifyError( MySqlStrings.IncompatibleTableMemoryOptimizedMismatch("Table", nameof(A), nameof(B), nameof(A), nameof(B)), modelBuilder.Model); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected override void ValidateMapping(CoreTypeMapping mapping, IProperty property) { var relationalMapping = mapping as RelationalTypeMapping; if (_disallowedMappings.Contains(relationalMapping?.StoreType)) { if (property == null) { throw new ArgumentException(MySqlStrings.UnqualifiedDataType(relationalMapping.StoreType)); } throw new ArgumentException(MySqlStrings.UnqualifiedDataTypeOnProperty(relationalMapping.StoreType, property.Name)); } }
private static (string Schema, string Table) Parse(string table) { var match = _partExtractor.Match(table.Trim()); if (!match.Success) { throw new InvalidOperationException(MySqlStrings.InvalidTableToIncludeInScaffolding(table)); } var part1 = match.Groups["part1"].Value.Replace("]]", "]"); var part2 = match.Groups["part2"].Value.Replace("]]", "]"); return(string.IsNullOrEmpty(part2) ? (null, part1) : (part1, part2)); }
public void Throws_setting_identity_generation_for_invalid_type() { var modelBuilder = GetModelBuilder(); var property = modelBuilder .Entity <Customer>() .Property(e => e.Name) .Metadata; Assert.Equal( MySqlStrings.IdentityBadType("Name", nameof(Customer), "string"), Assert.Throws <ArgumentException>( () => property.SetValueGenerationStrategy(MySqlValueGenerationStrategy.IdentityColumn)).Message); }
public void Contains_should_throw_on_client_eval() { var exNoLang = Assert.Throws <InvalidOperationException>(() => EF.Functions.Contains("teststring", "teststring")); Assert.Equal( MySqlStrings.FunctionOnClient(nameof(MySqlDbFunctionsExtensions.Contains)), exNoLang.Message); var exLang = Assert.Throws <InvalidOperationException>(() => EF.Functions.Contains("teststring", "teststring", 1033)); Assert.Equal( MySqlStrings.FunctionOnClient(nameof(MySqlDbFunctionsExtensions.Contains)), exLang.Message); }
public void Throws_setting_identity_generation_for_invalid_type_only_with_explicit() { var propertyBuilder = CreateBuilder() .Entity(typeof(Splot), ConfigurationSource.Convention) .Property("Name", typeof(string), ConfigurationSource.Convention); Assert.False( propertyBuilder.MySql(ConfigurationSource.Convention) .ValueGenerationStrategy(MySqlValueGenerationStrategy.IdentityColumn)); Assert.Equal( MySqlStrings.IdentityBadType("Name", nameof(Splot), "string"), Assert.Throws <ArgumentException>( () => propertyBuilder.MySql(ConfigurationSource.Explicit).ValueGenerationStrategy(MySqlValueGenerationStrategy.IdentityColumn)).Message); }
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( MySqlStrings.UnqualifiedDataTypeOnProperty(typeName, nameof(StringCheese.StringWithSize)), Assert.Throws <ArgumentException>(() => mapper.FindMapping(property)).Message); }
public void Throws_setting_sequence_generation_for_invalid_type() { var propertyBuilder = CreateBuilder() .Entity(typeof(Splot)) .Property(typeof(string), "Name"); Assert.Equal( MySqlStrings.SequenceBadType("Name", nameof(Splot), "string"), Assert.Throws <ArgumentException>( () => propertyBuilder.HasValueGenerationStrategy(MySqlValueGenerationStrategy.SequenceHiLo)).Message); Assert.Equal( MySqlStrings.SequenceBadType("Name", nameof(Splot), "string"), Assert.Throws <ArgumentException>( () => new PropertyBuilder((IMutableProperty)propertyBuilder.Metadata).UseHiLo()).Message); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected virtual void ValidateNonKeyValueGeneration([NotNull] IModel model) { foreach (var property in model.GetEntityTypes() .SelectMany(t => t.GetDeclaredProperties()) .Where( p => ((MySqlPropertyAnnotations)p.MySql()).GetMySqlValueGenerationStrategy(fallbackToModel: false) == MySqlValueGenerationStrategy.SequenceHiLo && !p.IsKey() && p.ValueGenerated != ValueGenerated.Never && (!(p.FindAnnotation(MySqlAnnotationNames.ValueGenerationStrategy) is ConventionalAnnotation strategy) || !ConfigurationSource.Convention.Overrides(strategy.GetConfigurationSource())))) { throw new InvalidOperationException( MySqlStrings.NonKeyValueGeneration(property.Name, property.DeclaringEntityType.DisplayName())); } }
public void Throws_setting_identity_generation_for_invalid_type_only_with_explicit() { var propertyBuilder = CreateBuilder() .Entity(typeof(Splot)) .Property(typeof(string), "Name"); Assert.Equal( MySqlStrings.IdentityBadType("Name", nameof(Splot), "string"), Assert.Throws <ArgumentException>( () => propertyBuilder.HasValueGenerationStrategy(MySqlValueGenerationStrategy.IdentityColumn)).Message); Assert.Equal( MySqlStrings.IdentityBadType("Name", nameof(Splot), "string"), Assert.Throws <ArgumentException>( () => new PropertyBuilder((IMutableProperty)propertyBuilder.Metadata).UseIdentityColumn()).Message); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected override void ValidateSharedColumnsCompatibility(IReadOnlyList <IEntityType> mappedTypes, string tableName) { base.ValidateSharedColumnsCompatibility(mappedTypes, tableName); var identityColumns = new List <IProperty>(); var propertyMappings = new Dictionary <string, IProperty>(); foreach (var property in mappedTypes.SelectMany(et => et.GetDeclaredProperties())) { var propertyAnnotations = property.Relational(); var columnName = propertyAnnotations.ColumnName; if (propertyMappings.TryGetValue(columnName, out var duplicateProperty)) { var propertyStrategy = property.MySql().ValueGenerationStrategy; var duplicatePropertyStrategy = duplicateProperty.MySql().ValueGenerationStrategy; if (propertyStrategy != duplicatePropertyStrategy && (propertyStrategy == MySqlValueGenerationStrategy.IdentityColumn || duplicatePropertyStrategy == MySqlValueGenerationStrategy.IdentityColumn)) { throw new InvalidOperationException( MySqlStrings.DuplicateColumnNameValueGenerationStrategyMismatch( duplicateProperty.DeclaringEntityType.DisplayName(), duplicateProperty.Name, property.DeclaringEntityType.DisplayName(), property.Name, columnName, tableName)); } } else { propertyMappings[columnName] = property; if (property.MySql().ValueGenerationStrategy == MySqlValueGenerationStrategy.IdentityColumn) { identityColumns.Add(property); } } } if (identityColumns.Count > 1) { var sb = new StringBuilder() .AppendJoin(identityColumns.Select(p => "'" + p.DeclaringEntityType.DisplayName() + "." + p.Name + "'")); throw new InvalidOperationException(MySqlStrings.MultipleIdentityColumns(sb, tableName)); } }
public void Detects_non_key_SequenceHiLo(bool obsolete) { var modelBuilder = CreateConventionalModelBuilder(); if (obsolete) { #pragma warning disable 618 modelBuilder.Entity <Dog>().Property(c => c.Type).ForMySqlUseSequenceHiLo(); #pragma warning restore 618 } else { modelBuilder.Entity <Dog>().Property(c => c.Type).UseHiLo(); } VerifyError(MySqlStrings.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)).ForMySqlInclude(nameof(Dog.Name)); #pragma warning restore 618 } else { modelBuilder.Entity <Dog>().HasIndex(nameof(Dog.Name)).IncludeProperties(nameof(Dog.Name)); } VerifyError(MySqlStrings.IncludePropertyInIndex(nameof(Dog), nameof(Dog.Name)), modelBuilder.Model); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected override void ValidateSharedTableCompatibility( IReadOnlyList <IEntityType> mappedTypes, string tableName) { var firstMappedType = mappedTypes[0]; var isMemoryOptimized = firstMappedType.MySql().IsMemoryOptimized; foreach (var otherMappedType in mappedTypes.Skip(1)) { if (isMemoryOptimized != otherMappedType.MySql().IsMemoryOptimized) { throw new InvalidOperationException( MySqlStrings.IncompatibleTableMemoryOptimizedMismatch( tableName, firstMappedType.DisplayName(), otherMappedType.DisplayName(), isMemoryOptimized ? firstMappedType.DisplayName() : otherMappedType.DisplayName(), !isMemoryOptimized ? firstMappedType.DisplayName() : otherMappedType.DisplayName())); } } base.ValidateSharedTableCompatibility(mappedTypes, tableName); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected virtual void ValidateIndexIncludeProperties([NotNull] IModel model) { foreach (var index in model.GetEntityTypes().SelectMany(t => t.GetDeclaredIndexes())) { var includeProperties = index.MySql().IncludeProperties; if (includeProperties?.Count > 0) { var notFound = includeProperties .Where(i => index.DeclaringEntityType.FindProperty(i) == null) .FirstOrDefault(); if (notFound != null) { throw new InvalidOperationException( MySqlStrings.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( MySqlStrings.IncludePropertyDuplicated(index.DeclaringEntityType.DisplayName(), duplicate)); } var inIndex = includeProperties .Where(i => index.Properties.Any(p => i == p.Name)) .FirstOrDefault(); if (inIndex != null) { throw new InvalidOperationException( MySqlStrings.IncludePropertyInIndex(index.DeclaringEntityType.DisplayName(), inIndex)); } } } }
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).UseMySqlIdentityColumn(); modelBuilder.Entity <Dog>().Property <int?>("Tag").UseMySqlIdentityColumn(); #pragma warning restore 618 } else { modelBuilder.Entity <Dog>().Property(c => c.Type).UseIdentityColumn(); modelBuilder.Entity <Dog>().Property <int?>("Tag").UseIdentityColumn(); } VerifyError(MySqlStrings.MultipleIdentityColumns("'Dog.Tag', 'Dog.Type'", nameof(Dog)), modelBuilder.Model); }
private static void CheckValueGenerationStrategy(IProperty 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())); } } }
/// <summary> /// <para> /// An implementation of the SQL MATCH operation for Full Text search. /// </para> /// <para> /// The semantics of the comparison will depend on the database configuration. /// In particular, it may be either case-sensitive or /// case-insensitive. /// </para> /// <para> /// Should be directly translated to SQL. /// This function can't be evaluated on the client. /// </para> /// </summary> /// <param name="_">The DbFunctions instance.</param> /// <param name="matchExpression">The property of entity that is to be matched.</param> /// <param name="pattern">The pattern against which Full Text search is performed</param> /// <param name="searchMode">Mode in which search is performed</param> /// <returns>true if there is a match.</returns> /// <exception cref="InvalidOperationException">Throws when query switched to client-evaluation.</exception> public static bool Match <T>( [CanBeNull] this DbFunctions _, [CanBeNull] T matchExpression, [CanBeNull] string pattern, MySqlMatchSearchMode searchMode) => throw new InvalidOperationException(MySqlStrings.FunctionOnClient(nameof(Match)));