Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,13 @@ protected override void ValidateIndex(
ValidateIndexIncludeProperties(index);
ValidateFullTextIndex(index);
ValidateVectorIndex(index);

#pragma warning disable EF1001 // Internal EF Core API usage.
if (index.IsJsonIndex())
#pragma warning restore EF1001 // Internal EF Core API usage.
{
ValidateUnsupportedJsonIndexOptions(index);
}
}

/// <summary>
Expand Down Expand Up @@ -425,6 +432,29 @@ protected virtual void ValidateVectorIndex(IIndex index)
}
}

private static void ValidateUnsupportedJsonIndexOptions(IIndex index)
{
var option = index switch
{
{ IsUnique: true } => nameof(index.IsUnique),
{ IsDescending: not null } => nameof(index.IsDescending),
_ when index.GetFilter() is not null => "Filter",
_ when index.IsClustered() is true => "IsClustered",
_ when index.GetIncludeProperties()?.Count > 0 => "IncludeProperties",
_ when index.IsCreatedOnline() is true => "IsCreatedOnline",
_ when index.GetSortInTempDb() is true => "SortInTempDb",
_ when index.GetDataCompression() is not null => "DataCompression",
_ => null
};

if (option is not null)
{
throw new InvalidOperationException(
SqlServerStrings.JsonIndexUnsupportedOption(
index.DisplayName(), index.DeclaringEntityType.DisplayName(), option));
}
}

private static void ValidateUnsupportedIndexOptions(IIndex index, Func<string, string> errorFactory)
{
var option = index switch
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/EFCore.SqlServer/Properties/SqlServerStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@
<data name="InvalidTableToIncludeInScaffolding" xml:space="preserve">
<value>The specified table '{table}' is not in a valid format. Specify tables using the format '[schema].[table]'.</value>
</data>
<data name="JsonIndexUnsupportedOption" xml:space="preserve">
<value>JSON index '{index}' on entity type '{entityType}' was configured with the '{option}' option, which is not supported on JSON indexes.</value>
</data>
<data name="JsonValuePathExpressionsNotSupported" xml:space="preserve">
<value>A non-constant array index or property name was used when navigating inside a JSON document, but EF Core's SQL Server compatibility level is set to {compatibilityLevel}; this is only supported with compatibility level 140 (SQL Server 2017) or higher.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,88 @@ protected class EntityWithIncludedComplexAddress
public required string Street { get; set; }
}

[Theory]
[InlineData("IsUnique")]
[InlineData("IsDescending")]
[InlineData("Filter")]
[InlineData("IsClustered")]
[InlineData("IncludeProperties")]
[InlineData("IsCreatedOnline")]
[InlineData("SortInTempDb")]
[InlineData("DataCompression")]
public void Json_index_with_unsupported_option_throws(string option)
{
var modelBuilder = CreateConventionModelBuilder();
modelBuilder.Entity<EntityWithIncludedComplexJson>(b =>
{
b.ComplexProperty(e => e.Address, cb => cb.ToJson());
var indexBuilder = b.HasIndex("Address.City");

switch (option)
{
case "IsUnique":
indexBuilder.IsUnique();
break;
case "IsDescending":
indexBuilder.IsDescending();
break;
case "Filter":
indexBuilder.HasFilter("[Id] > 0");
break;
case "IsClustered":
indexBuilder.IsClustered();
break;
case "IncludeProperties":
indexBuilder.IncludeProperties("Id");
break;
case "IsCreatedOnline":
indexBuilder.IsCreatedOnline();
break;
case "SortInTempDb":
indexBuilder.SortInTempDb();
break;
case "DataCompression":
indexBuilder.Metadata.SetDataCompression(DataCompressionType.Page);
break;
default:
throw new InvalidOperationException();
}
});

VerifyError(
SqlServerStrings.JsonIndexUnsupportedOption(
"{'City'}", nameof(EntityWithIncludedComplexJson), option),
modelBuilder);
}

[Theory]
[InlineData("FillFactor")]
[InlineData("NonClustered")]
[InlineData("NoIncludeProperties")]
[InlineData("CreatedOffline")]
[InlineData("SortInTempDbDisabled")]
public void Json_index_with_supported_option_passes(string option)
{
var modelBuilder = CreateConventionModelBuilder();
modelBuilder.Entity<EntityWithIncludedComplexJson>(b =>
{
b.ComplexProperty(e => e.Address, cb => cb.ToJson());
var indexBuilder = b.HasIndex("Address.City");

_ = option switch
{
"FillFactor" => indexBuilder.HasFillFactor(80),
"NonClustered" => indexBuilder.IsClustered(false),
"NoIncludeProperties" => indexBuilder.IncludeProperties(),
"CreatedOffline" => indexBuilder.IsCreatedOnline(false),
"SortInTempDbDisabled" => indexBuilder.SortInTempDb(false),
_ => throw new InvalidOperationException()
};
});

Validate(modelBuilder);
}

[Fact]
public virtual void Detects_incompatible_memory_optimized_shared_table()
{
Expand Down
Loading