2012-05-16 20 views
80

Używam Entity Framework 4.3 i używając Code Fist.Kod obiektu Entity Framework first unique column

Mam klasy

public class User 
{ 
    public int UserId{get;set;} 
    public string UserName{get;set;} 
} 

Jak mogę powiedzieć, że nazwa_użytkownika Entity Framework musi być unikalna przy tworzeniu tabeli bazy danych? Wolałbym użyć danych liczbowych zamiast pliku konfiguracyjnego, jeśli to możliwe.

Odpowiedz

-13

rozwiązanie dla EF4.3

unikalną Nazwę

Dodaj adnotacji danych na kolumny jak:

[Index(IsUnique = true)] 
[MaxLength(255)] // for code-first implementations 
public string UserName{get;set;} 

unikatowy identyfikator , Dodałem Dekoracja [Key] nad moja kolumna i gotowe. samo rozwiązanie jak opisano tutaj: https://msdn.microsoft.com/en-gb/data/jj591583.aspx

IE:

[Key] 
public int UserId{get;set;} 

alternatywna odpowiedzi

używając adnotacji dane dotyczą

[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
[Column("UserId")] 

Korzystanie mapowanie

mb.Entity<User>() 
      .HasKey(i => i.UserId); 
     mb.User<User>() 
      .Property(i => i.UserId) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) 
      .HasColumnName("UserId"); 
+24

Uważaj na to rozwiązanie. Dodanie atrybutu 'Key' do właściwości' UserName' spowoduje, że właściwość 'UserName' stanie się kluczem podstawowym w bazie danych. Tylko właściwość 'UserId' powinna być oznaczona za pomocą atrybutu' Key'. To rozwiązanie zapewni "prawidłowe" zachowanie po stronie programowania, jednocześnie dając niepoprawny projekt bazy danych. –

+4

zabawna -10 zaakceptowana odpowiedź :) –

20

EF nie obsługuje unikalnych kolumn oprócz kluczy. Jeśli korzystasz z Migracji EF, możesz wymusić na EF utworzenie unikalnego indeksu na kolumnie UserName (w kodzie migracji, a nie w adnej adnotacji), ale unikalność będzie egzekwowana tylko w bazie danych. Jeśli spróbujesz zapisać zduplikowaną wartość, będziesz musiał wychwycić wyjątek (naruszenie ograniczenia) wystrzelony przez bazę danych.

+1

Tego właśnie szukałem! Zastanawiam się, czy możliwe było dodanie takich ograniczeń przy użyciu migracji. –

+0

@ Ladislav Mrnka: Czy jest to również możliwe za pomocą metody Seed? –

+1

Chcesz podać przykład? Dzięki! – Zero3

5

Należy zauważyć, że w Entity Framework 6.1 (obecnie w wersji beta) będzie obsługiwane IndexAttribute w celu adnotowania właściwości indeksu, który automatycznie spowoduje (unikalny) indeks w swoim kodzie First Migrations.

170

W Entity Framework 6.1+ można używać tego atrybutu modelu:

[Index(IsUnique=true)] 

Można go znaleźć w tej przestrzeni nazw:

using System.ComponentModel.DataAnnotations.Schema; 

Jeśli pole model jest ciągiem znaków, upewnij się, nie jest ustawiony na nvarchar (MAX) w SQL Server lub zobaczysz ten błąd z Entity Framework Code Najpierw:

Kolumna "x" w tabeli "dbo.y" i s typu niepoprawnego do użycia jako kolumna kluczowa w indeksie.

Powodem jest z tego powodu:

SQL Server zachowuje limit 900-bajtowy dla maksymalnej łącznej wielkości wszystkich kolumn klucza indeksu."

(od: http://msdn.microsoft.com/en-us/library/ms191241.aspx)

Problem ten można rozwiązać poprzez ustawienie maksymalnej długości ciąg modelu:

[StringLength(450)] 

Twój model będzie wyglądać teraz w EF CF 6.1 +:

public class User 
{ 
    public int UserId{get;set;} 
    [StringLength(450)] 
    [Index(IsUnique=true)] 
    public string UserName{get;set;} 
} 

Aktualizacja:

jeśli używasz Zaawansowany:

public class UserMap : EntityTypeConfiguration<User> 
    { 
    public UserMap() 
    { 
     // .... 
     Property(x => x.Name).IsRequired().HasMaxLength(450).HasColumnAnnotation("Index", new IndexAnnotation(new[] { new IndexAttribute("Index") { IsUnique = true } })); 
    } 
    } 

i używać w ModelBuilder:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    // ... 
    modelBuilder.Configurations.Add(new UserMap()); 
    // ... 
} 

Update 2

dla EntityFrameworkCore patrz także ten temat: https://github.com/aspnet/EntityFrameworkCore/issues/1698

+14

Dzięki za odpowiedź na stary post tego faceta z kilkoma aktualnymi aktualnymi informacjami! –

+2

Ustawienie długości ciągu działa. świetna odpowiedź. – vidriduch

+1

dlaczego indeks, dlaczego nie tylko ograniczenie? –

8

Z twojego kodu wynika, że ​​używasz POCO. Posiadanie innego klucza jest niepotrzebne: możesz dodać indeks zgodnie z sugestią podaną pod numerem juFo.
Jeśli używasz Fluent API zamiast przypisywania właściwości UserName swoją adnotację kolumna powinna wyglądać następująco:

this.Property(p => p.UserName) 
    .HasColumnAnnotation("Index", new IndexAnnotation(new[] { 
     new IndexAttribute("Index") { IsUnique = true } 
    } 
)); 

To stworzy następujący skrypt SQL:

CREATE UNIQUE NONCLUSTERED INDEX [Index] ON [dbo].[Users] 
(
    [UserName] ASC 
) 
WITH (
    PAD_INDEX = OFF, 
    STATISTICS_NORECOMPUTE = OFF, 
    SORT_IN_TEMPDB = OFF, 
    IGNORE_DUP_KEY = OFF, 
    DROP_EXISTING = OFF, 
    ONLINE = OFF, 
    ALLOW_ROW_LOCKS = ON, 
    ALLOW_PAGE_LOCKS = ON 
) ON [PRIMARY] 

przypadku próby wstawienia wielu użytkowników posiadających to samo UserName otrzymasz wyjątek DbUpdateException z następującym komunikatem:

Cannot insert duplicate key row in object 'dbo.Users' with unique index 'Index'. 
The duplicate key value is (...). 
The statement has been terminated. 

Znów, kolumna annotati nie są dostępne w Entity Framework przed wersją 6.1.

Powiązane problemy