Skip to content

Unable to suppress filter on unique index with .HasFilter(null) since EF Core 3 #20136

@miniyou

Description

@miniyou

A unique index where at least one column is nullable will by default get a filter like [SomeColumn] IS NOT NULL. With EF Core 2, this filter could be suppressed with .HasFilter(null) in the fluent definition, like so:

x.Entity<CompanyExternalAuthToken>()
    .HasIndex(d => new { d.ServiceKey, d.ExternalId })
    .HasName("IX_ServiceKey_ExternalId")
    .IsUnique(true)
    .HasFilter(null);

However, with EF Core 3.1, the HasFilter call has no effect, the result is the same as if it had not been called at all. In other words, when creating a migration, EF Core will try to recreate all of those indexes to include the filter we're trying to suppress.

I found a workaround and verified that it works as expected:

x.Entity<CompanyExternalAuthToken>()
    .HasIndex(d => new { d.ServiceKey, d.ExternalId })
    .HasName("IX_ServiceKey_ExternalId")
    .IsUnique(true)
    .Metadata.SetAnnotation(RelationalAnnotationNames.Filter, null);

It appears to me that this is caused by this snippet – note the call to SetOrRemoveAnnotation rather than SetAnnotation:

public static void SetFilter([NotNull] this IMutableIndex index, [CanBeNull] string value)
    => index.SetOrRemoveAnnotation(
        RelationalAnnotationNames.Filter,
        Check.NullButNotEmpty(value, nameof(value)));

I don't see any reason for this change, and it seems unintentional to me.

Steps to reproduce

Create an entity with at least one nullable column, like

public class MyEntity
{
    public string MyProperty { get; set; }
    // ...others omitted for brevity
}

In OnModelCreating(…), define this index:

x.Entity<MyEntity>()
    .HasIndex(d => new { d.MyProperty })
    .HasName("IX_MyProperty")
    .IsUnique(true)
    .HasFilter(null);

Result: the index gets a filter.

Further technical details

EF Core version: 3.1.2 (upgrading from 2.2.4-servicing-10062)
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET Framework 4.7.2
Operating system: Windows 10
IDE: Visual Studio Enterprise 2019 16.4.3

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions