【问题标题】:Case insensitive unique constraint for Postgres + EF CorePostgres + EF Core 的不区分大小写的唯一约束
【发布时间】:2020-07-22 18:57:13
【问题描述】:

我正在使用 Postgres + EF Core。我有一个名为 Name 的列,我希望它是唯一的。我尝试了以下方法:

builder.HasIndex(s => s.Name).IsUnique();

但这允许“test123”和“TEST123”被接受。如何使用 fluent api 添加不区分大小写的唯一约束?

或者我只需要创建一个 NormalizedName 列并向其中添加唯一约束。每次我想向列添加唯一约束时,似乎需要做很多工作。

【问题讨论】:

    标签: asp.net-mvc postgresql asp.net-core entity-framework-core


    【解决方案1】:

    如果您使用的是 EF Core 5.0,请参见下文(可能是更好的解决方案)。否则,我通过使用citext 扩展名添加了不区分大小写的检查,如here 所述。有一些限制,我不会在这里列出,但是您可以在上一个链接中阅读它们或直接在PostgreSQL Docs上阅读。

    还要确保您已安装 postgres-contrib 软件包以使用此扩展。

    首先,通过将扩展添加到模型构建器来启用它

    modelBuilder.HasPostgresExtension("citext");
    

    然后使用citext作为列类型

    builder.Property(s => s.Name)
           .HasColumnType("citext")
    

    EF Core 5.0

    在 EF Core 5.0 中,使用 Collations 可以获得更好的支持。您还可以查看有关 PostrgeSQL 的 Npgsql docs。这克服了上面citext 的一系列限制,并为您提供了更多控制权。

    所以(未经测试的)步骤是:

    1. 使用 ICU 创建一个排序规则作为数据库对象。这将创建一个不确定的、不区分大小写的 ICU 排序规则。如果您需要其他内容,请查看ICU docs
    modelBuilder.HasCollation("case_insensitive_collation", locale: "en-u-ks-primary", provider: "icu", deterministic: false);
    
    1. 现在在您的专栏中,您可以添加:
    builder.HasIndex(s => s.Name)
           .UseCollation("case_insensitive_collation")
           .IsUnique();
    

    如果你以其他方式实现它,我很想听听如何。

    【讨论】:

    • 使用 npgsql 的预览版(当前最新的是 5.0.0-rc1)然后是的,你可以。
    • 谢谢,如果您有两个不区分大小写的列,并且它们必须是唯一的。使用 Property 使它们不区分大小写,然后添加唯一索引,或者像您一样添加带有排序规则的唯一索引更好吗?如果您使用索引,列是否仍会使用该索引之外的排序规则?
    • 好问题,我不确定排序规则是否是“继承”的。也许你可以测试一下。但我想我可能会尝试在.HasIndex(p => new {p.FirstColumn , p.SecondColumn}) 列上创建一个索引,然后将UseCollation 链接到该列。至少我认为索引应该是唯一的意图更清楚了?
    • EF Core 5.0 版本非常适合我,谢谢!
    猜你喜欢
    • 2016-12-24
    • 2013-05-30
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    相关资源
    最近更新 更多