Entity Framework Core fügt zuerst einen eindeutigen Einschränkungscode hinzu


152

Ich kann mit dem folgenden Attribut keine Möglichkeit finden, meinem Feld eine eindeutige Einschränkung hinzuzufügen:

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; }
}

Ich benutze diese Pakete:

 "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",

Beispiele für fließende APIs
Michael Freidgeim

Antworten:


300

Auf EF Core können Sie keine Indizes mithilfe von Datenanmerkungen erstellen. Sie können dies jedoch mithilfe der Fluent-API tun.

So in deinem {Db}Context.cs:

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

... oder wenn Sie die Überladung mit der buildAction verwenden:

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

Mehr dazu lesen Sie hier: Indizes


1
Vielen Dank für Ihre Hilfe, es ist die richtige Lösung!
Vadim M

Für den Fall, dass jemand hier landet und nach einer Lösung sucht, die bei Verwendung des MS Identity-Schemas funktioniert, empfehle ich, die eindeutige Einschränkung für das Feld NormalizedEmail und nicht für E-Mail (der AspNetUsers-Entität) festzulegen. Je nach Kollatierungseinstellung der Datenbank kann die Verwendung eines anderen Falls die Verletzung möglicherweise nicht verletzen, selbst wenn es sich um dieselbe E-Mail-Adresse handelt.
Tom

4
Dieser Code funktioniert nicht für Spalten vom Typ Zeichenfolge :( Gibt es eine Möglichkeit, eine eindeutige Einschränkung für die Zeichenfolgenspalte hinzuzufügen?
Johar Zaman

Gehen Sie fürHasAlternateKey
Chamika Sandamal

1
Ich habe es versucht, als ich daran gearbeitet habe, aber jetzt muss ich das nicht implementieren. Übrigens Vielen Dank für Ihren Kommentar. @ Sampath
Johar Zaman

70

Auch wenn Sie eindeutige Einschränkungen für mehrere Spalten erstellen möchten, können Sie dies einfach tun (folgen Sie dem Link von @ Sampath ).

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; }
}

9

Lösung für 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})
    }
}

Die DB-Tabelle sieht folgendermaßen aus:

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)
);

Siehe EF Core-Dokumente


11
Laut EF Core-Dokumenten: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

Verweis auf den Kommentar von bigworld12
granadaCoder

3

Das OP fragt, ob es möglich ist, einer Entitätsklasse ein Attribut für einen eindeutigen Schlüssel hinzuzufügen. Die kurze Antwort lautet, dass dies möglich ist, jedoch keine sofort einsatzbereite Funktion des EF Core-Teams. Wenn Sie ein Attribut verwenden möchten, um Ihren Entity Framework Core-Entitätsklassen eindeutige Schlüssel hinzuzufügen, können Sie das tun, was ich hier gepostet habe

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; }
}

Das Attribut [UniqueKey] ist ein von Microsoft definiertes Attribut. oder sollte man es selbst definieren?
Mohammed Osman

Das [UniqueKey] -Attribut ist ein benutzerdefiniertes Attribut, das ich entwickelt habe, um das Hinzufügen eindeutiger Schlüssel innerhalb der .cs-Entitätsklassen zu ermöglichen (und nicht über die OnModelCreating () -Methode von DbContext)
Justin Tubbs,

3
Das ist großartig. Könnten Sie bitte den Code des von Ihnen entwickelten benutzerdefinierten Attributs eingeben?!
Mohammed Osman


2

Für jemanden, der all diese Lösungen ausprobiert, aber nicht funktioniert, versuchen Sie diese, es hat für mich funktioniert

protected override void OnModelCreating(ModelBuilder builder)
{

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

}

2

Verwendung im EF-Kern über die Modellkonfiguration

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

1

Keine dieser Methoden funktionierte in .NET Core 2.2 für mich, aber ich konnte einen Code anpassen, den ich zum Definieren eines anderen Primärschlüssels für diesen Zweck hatte.

In der folgenden Instanz möchte ich sicherstellen, dass das Feld OutletRef eindeutig ist:

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

Dadurch wird der erforderliche eindeutige Index in die Datenbank eingefügt. Was es jedoch nicht tut, ist die Möglichkeit, eine benutzerdefinierte Fehlermeldung anzugeben.


0

Wir können einen eindeutigen Schlüsselindex hinzufügen, indem wir eine fließende API verwenden. Der folgende Code hat bei mir funktioniert

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

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

    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.