我的实体有一个允许为null的属性。但是,如果它不为空,那么它必须是唯一的。换句话说,该列是唯一的,但允许多个空值。
我试过了:
config.Property(p => p.ProductId).IsRequired(false);
我记得在前核心EF中努力工作。
这可能吗?如何配置实体?
答案 0 :(得分:6)
是的,您可以使用EF Core执行此操作,因为默认情况下,唯一索引创建为筛选索引(WHERE ... IS NOT NULL)
config.Entity<Product>()
.HasIndex(b => b.ProductId)
.IsUnique();
答案 1 :(得分:0)
我知道这是旧的,但是对于那些现在找到它的人来说,我在 EF Core 5.0 中看到的默认行为与已接受的答案中描述的不同。您可以为索引显式指定过滤器,这是我刚刚创建的一个示例:
modelBuilder.Entity<Reef>(etb =>
{
// ...
etb.HasIndex(r => r.Label)
.HasFilter("Label IS NOT NULL")
.IsUnique();
// ...
});
编辑:
我想我已经找到了完整的答案。如果您有一个可为空值类型的属性,并且您在该属性上创建了一个唯一索引,那么该索引将默认有一个过滤器。但是,如果属性是引用类型,则必须使用 fluent API 或属性指定它可以为空作为额外步骤。我没有使用属性进行测试,但是,使用 fluent API,默认情况下生成的索引不会有过滤器。考虑以下实体:
public class Thing
{
public int ThingId { get; set; }
public string Text { get; set; }
public int? StuffId { get; set; }
public Stuff Stuff { get; set; }
}
在 DbContext
中包含以下内容:
modelBuilder.Entity<Thing>(etb =>
{
etb.Property(t => t.Text)
.IsRequired(false);
etb.HasIndex(t => t.Text)
.IsUnique();
etb.HasIndex(t => t.StuffId)
.IsUnique();
});
在 StuffId
列上生成的唯一索引默认会有一个过滤器,而 Text
上的唯一索引没有。必须为 Text
列索引明确指定过滤器:
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();
});