添加包含可为空值的唯一约束

问题描述 投票:0回答:1

我有以下实体模型:

    public class RoutePermission
    {
        public Guid? UserId { get; set; }
        public Guid? DistrictId { get; set; }
        public Guid RouteId { get; set; }
        public bool Admin { get; set; }
    }

我想添加一个唯一的约束来实现以下行为:

{ routeId: 1, userId: 1, districtId: null, admin: true } // Allowed
{ routeId: 1, userId: null, districtId: 1, admin: true } // Allowed
{ routeId: 2, userId: 1, districtId: null, admin: true } // Allowed
{ routeId: 2, userId: 1, districtId: null, admin: true } // Not Allowed

问题是插入第四条记录时没有抛出错误。

这是我开始的模型验证:

modelBuilder.Entity<RoutePermission>()
   .HasIndex(rp =>
      new { rp.RouteId, rp.DistrictId, rp.UserId }
   )
   .IsUnique();

没有骰子。我做了很多研究,并且发现了

.HasFilter(null)
,据说它会覆盖在任何已验证字段为空时跳过验证的默认行为。我明白了!不,还是什么都没有。

我终于发现真正的问题是什么了。 Postgres 认为

null
值与另一个值indistinct,因此 null != null (就像 JavaScript 中的对象一样)。现在我明白了为什么 Postgres 没有为上面示例中的第四条记录抛出任何错误。但如何解决呢?

.net postgresql entity-framework-core unique-constraint
1个回答
0
投票

ChatGPT 建议使用

COALESCE
将空值替换为等于另一个类似值的值。虽然
null != null
,但如果我们用 0 替换空值,
0 = 0
并且验证应该按预期进行。唉,还是没有骰子。

像往常一样,这个解决方案让我感觉很愚蠢。

最终的、复杂的 SQl-custom-filter-bypassing-ef-core-limitations?

.AreNullsDistinct(false);

😒

最终解决方案/#TDLR

   modelBuilder
   .Entity<RoutePermission>()
   .HasIndex(rp =>
      new { rp.RouteId, rp.DistrictId, rp.UserId }
   )
   .IsUnique()
   .AreNullsDistinct(false);
© www.soinside.com 2019 - 2024. All rights reserved.