I know this is old but, for those who find it now, the default behaviour I'm seeing in EF Core 5.0 is not what's described in the accepted answer. You can specify a filter for an index explicitly and here's an example of one I just created:
modelBuilder.Entity<Reef>(etb =>
{
// ...
etb.HasIndex(r => r.Label)
.HasFilter("Label IS NOT NULL")
.IsUnique();
// ...
});
EDIT:
I think that I have worked out the complete answer. If you have a property that is a nullable value type and you create a unique index on that then that index will have a filter by default. If the property is a reference type though, you have to specify that it is nullable as an extra step, either using the fluent API or an attribute. I haven't tested with an attribute but, using the fluent API, the resulting index will not have a filter by default. Consider the following entity:
public class Thing
{
public int ThingId { get; set; }
public string Text { get; set; }
public int? StuffId { get; set; }
public Stuff Stuff { get; set; }
}
With the following in the DbContext
:
modelBuilder.Entity<Thing>(etb =>
{
etb.Property(t => t.Text)
.IsRequired(false);
etb.HasIndex(t => t.Text)
.IsUnique();
etb.HasIndex(t => t.StuffId)
.IsUnique();
});
The unique index generated on the StuffId
column will have a filter by default while the one on Text
will not. A filter must be specified explicitly for the Text
column index:
modelBuilder.Entity<Thing>(etb =>
{
etb.Property(t => t.Text)
.IsRequired(false);
etb.HasIndex(t => t.Text)
.HasFilter("Text IS NOT NULL")
.IsUnique();
etb.HasIndex(t => t.StuffId)
.IsUnique();
});