ChatGPT解决这个技术问题 Extra ChatGPT

Entity Framework Core 添加唯一约束代码优先

我找不到使用属性向我的字段添加唯一约束的方法:

public class User
{
    [Required]
    public int Id { get; set; }

    [Required]
    // [Index("IX_FirstAndSecond", 2, IsUnique = true)] not supported by core
    public string Email { get; set; }

    [Required]
    public string Password { get; set; }
}

我正在使用这些软件包:

 "Microsoft.EntityFrameworkCore": "1.0.1",
 "Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
 "Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.1",
 "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
用于索引的 fluent Api 示例参见 learnentityframeworkcore.com/configuration/fluent-api/…

S
Sampath

在 EF 核心上,您无法使用数据注释创建索引。但您可以使用 Fluent API 来创建索引。

在您的 {Db}Context.cs 中像这样:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>()
        .HasIndex(u => u.Email)
        .IsUnique();
}

...或者,如果您将重载与 buildAction 一起使用:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>(entity => {
        entity.HasIndex(e => e.Email).IsUnique();
    });
}

您可以在此处阅读更多信息:Indexes


非常感谢您的帮助,这是正确的解决方案!
如果有人在这里寻找在使用 MS Identity 架构时有效的解决方案,我建议在 NormalizedEmail 字段上设置唯一约束,而不是在电子邮件(AspNetUsers 实体的)上设置唯一约束。使用不同的大小写可能无法违反约束,即使它是相同的电子邮件地址,这取决于数据库的排序规则设置。
此代码不适用于字符串类型的列:(有没有办法在字符串列上添加唯一约束?
前往HasAlternateKey
我在做这个的时候试过这个,但现在我不需要实现这个。顺便说一句,谢谢您的评论。 @Sampath
H
Hossein Narimani Rad

此外,如果您想在多列上创建唯一约束,您可以简单地执行此操作(遵循 @Sampath 的 link

class MyContext : DbContext
{
    public DbSet<Person> People { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .HasIndex(p => new { p.FirstName, p.LastName })
            .IsUnique(true);
    }
}

public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

T
TiskSec365

从 Entity Framework Core (EF Core) 5.0 开始,我们可以configure Unique Indexes via Data Annotations

它与例如 EF6 几乎没有什么不同,因为我们不能在属性本身上设置它,而是在类上设置它。

[Index(nameof(EmailAddress), IsUnique = true)]
public class User
{
    [Key]
    public Guid Id { get; set; }

    [Required]
    public string FullName { get; set; }

    [Required]
    public string EmailAddress { get; set; }
}

有关索引和数据注释的更多信息,请参阅:https://docs.microsoft.com/en-us/ef/core/modeling/indexes?tabs=data-annotations


Index 属性位于命名空间 Microsoft.EntityFrameworkCore 上,需要 Microsoft.EntityFrameworkCore nuget 包。我将模型和 DbContext 放在不同的项目中,并且很难找到它认为它在 System.ComponentModel.DataAnnotations 上(它不是)。
E
Evgeniy Miroshnichenko

EF Core 解决方案

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Passport { get; set; }
}

public class ApplicationContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public ApplicationContext()
    {
        Database.EnsureCreated();
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=efbasicsappdb;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasAlternateKey(u => u.Passport);
        //or: modelBuilder.Entity<User>().HasAlternateKey(u => new { u.Passport, u.Name})
    }
}

数据库表将如下所示:

CREATE TABLE [dbo].[Users] (
    [Id]       INT            IDENTITY (1, 1) NOT NULL,
    [Name]     NVARCHAR (MAX) NULL,
    [Passport] NVARCHAR (450) NOT NULL,
    CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [AK_Users_Passport] UNIQUE NONCLUSTERED ([Passport] ASC)
);

Ref to EF Core docs


根据 EF Core 文档:If you just want to enforce uniqueness of a column then you want a unique index rather than an alternate key. In EF, alternate keys provide greater functionality than unique indexes because they can be used as the target of a foreign key.
参考 bigworld12 的评论:docs.microsoft.com/en-us/ef/core/modeling/…
V
ViRuSTriNiTy

Ef核心支持独特的配置。

protected override void OnModelCreating(ModelBuilder builder)
{
  builder.Entity<Account>()
    .HasIndex(account => account.Email)
      .IsUnique();
}

Ef核心支持多个唯一键

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<Account>()
      .HasKey(account => new { account.Id, account.Email, account.RoleId });
}

不要忘记运行 ef core 命令进行迁移和更新数据库

>> dotnet ef migrations add MigrationName -c YourDbContextName
>> dotnet ef database update -c YourDbContextName

v
valentasm

通过模型配置在 EF 核心中使用它

public class ApplicationCompanyConfiguration : IEntityTypeConfiguration<Company>
{
    public void Configure(EntityTypeBuilder<Company> builder)
    {
        builder.ToTable("Company"); 
        builder.HasIndex(p => p.Name).IsUnique();
    }
}

V
ViRuSTriNiTy

OP 询问是否可以将属性添加到实体类以获得唯一键。简短的回答是这是可能的,但不是 EF Core 团队的开箱即用功能。如果您想使用属性将唯一键添加到您的 Entity Framework Core 实体类,您可以按照我发布的here

public class Company
{
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid CompanyId { get; set; }

    [Required]
    [UniqueKey(groupId: "1", order: 0)]
    [StringLength(100, MinimumLength = 1)]
    public string CompanyName { get; set; }

    [Required]
    [UniqueKey(groupId: "1", order: 1)]
    [StringLength(100, MinimumLength = 1)]
    public string CompanyLocation { get; set; }
}

[UniqueKey] 属性是微软定义的属性吗?还是应该自己定义?
[UniqueKey] 属性是我开发的自定义属性,用于在 .cs 实体类中添加唯一键(而不是通过 DbContext 的 OnModelCreating() 方法)
那太棒了。你能把你开发的自定义属性的代码放上来吗?!
H
Hien Nguyen

对于尝试所有这些解决方案但不工作的人,试试这个,它对我有用

protected override void OnModelCreating(ModelBuilder builder)
{

    builder.Entity<User>().Property(t => t.Email).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_EmailIndex") { IsUnique = true }));

}

R
Robin Wilson

这些方法在 .NET Core 2.2 中都不适合我,但我能够调整一些用于定义不同主键的代码来实现此目的。

在下面的实例中,我想确保 OutletRef 字段是唯一的:

public class ApplicationDbContext : IdentityDbContext
    {
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Outlet>()
                .HasIndex(o => new { o.OutletRef });
        }
    }

这会在数据库中添加所需的唯一索引。但它没有提供指定自定义错误消息的能力。


K
Kuldeep Singh

我们可以使用 fluent api 添加唯一键索引。下面的代码对我有用

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<User>().Property(p => p.Email).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_EmailIndex") { IsUnique = true }));

    }