在 EF Core 中生成复合唯一约束/索引

Posted

技术标签:

【中文标题】在 EF Core 中生成复合唯一约束/索引【英文标题】:Generate a composite unique constraint/index, in EF Core 【发布时间】:2017-04-07 16:05:06 【问题描述】:

我需要为我的实体的 Name 属性设置一个复合唯一约束,该约束在 Category 中是唯一的(它有一个 FK)。

所以是这样的:

entityTypeBuilder
  .HasIndex(i => new  i.Name, i.Category.Id )
  .IsUnique();

但是由于Category.Id 导航属性,当我生成迁移时这会失败。

我知道我可以将值硬编码为字符串,但我不想丢失静态类型。

我有什么选择?

【问题讨论】:

【参考方案1】:

只要知道影子属性名称,就可以使用(至少在 EF Core 1.1.0 中)基于字符串的HasIndex 方法overload

public virtual IndexBuilder HasIndex(params string[] propertyNames)

例如

entityTypeBuilder
  .HasIndex("Name", "CategoryId")
  .IsUnique();

HasAlternateKey 也一样:

entityTypeBuilder
  .HasAlternateKey("Name", "CategoryId");

【讨论】:

是的,这就是我现在正在做的事情,正如我在问题中所说,你失去了静态类型。也许这是唯一的方法。 对于谁在阅读。您不会丢失静态类型。只需使用 nameof(Type.Property) 虽然失去了“”括号。 entityTypeBuilder.HasIndex("Name", "CategoryId").IsUnique(); @BenVertonghen 谢谢,已修复。【参考方案2】:

在相关实体上为类别 CategoryId 添加外键,并在索引构建器中使用它而不是导航属性。

【讨论】:

是的,但这很乱。这是唯一的选择吗? 你为什么认为这很乱?添加外键属性并不混乱,你为什么这么认为? @grokky @grokky - 我认为不定义外键属性很麻烦。 EF docs recommend it,而且,我宁愿不引入影子属性。 @kizilsu 它将与基础设施相关的属性添加到与域相关的类中。很乱。我不喜欢它,但似乎这是唯一可用的选项,而不是放弃静态类型。 @kizilsu 不,我不会那样做。但是 ORM 的重点是与数据库的工作相隔离。有时这是不可能的,比如这种情况。【参考方案3】:

作为对伊万出色回应的延伸:

如果你预先定义了外键,你至少可以控制名称关联

const string auditForeignKey = "AuditId";
builder.HasOne(e => e.Audit)
       .WithMany(e => e.AuditLocations)
       .HasForeignKey(auditForeignKey);

builder.HasIndex(auditForeignKey, nameof(AuditLocation.LocationId)).IsUnique();

【讨论】:

以上是关于在 EF Core 中生成复合唯一约束/索引的主要内容,如果未能解决你的问题,请参考以下文章

EF Core 迁移:在存在时删除唯一约束

EF Core 中是不是有用于唯一约束的数据注释(代码优先)?

如何使用jpa项目eclipse在实体类中生成唯一约束

在 EF Core 映射上添加唯一索引似乎不起作用

复合唯一键约束,其中一列中包含多个空值

mongodb 索引唯一性约束