EF Core是否允许唯一列包含多个空值?

时间:2017-01-03 08:39:04

标签: c# entity-framework ef-code-first entity-framework-core

我的实体有一个允许为null的属性。但是,如果它不为空,那么它必须是唯一的。换句话说,该列是唯一的,但允许多个空值。

我试过了:

config.Property(p => p.ProductId).IsRequired(false);

我记得在前核心EF中努力工作。

这可能吗?如何配置实体?

2 个答案:

答案 0 :(得分:6)

是的,您可以使用EF Core执行此操作,因为默认情况下,唯一索引创建为筛选索引(WHERE ... IS NOT NULL)

config.Entity<Product>()
        .HasIndex(b => b.ProductId)
        .IsUnique();

https://github.com/aspnet/EntityFramework/pull/2868

答案 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();
                          });