2012-05-16 4 views
80

Я использую Entity Framework 4.3 и используя Code Fist.Код Entity Framework первый уникальный столбец

У меня есть класс

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

Как узнать, Entity Framework, что UserName должен быть уникальным при создании таблицы базы данных? Я предпочел бы использовать данные вместо файла конфигурации, если это возможно.

ответ

-13

Раствор для EF4.3

Уникальный UserName

Добавить аннотацию данных по колонке как:

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

Unique ID , я добавил украшения [Key] над моя колонка и сделано. же решение, как описано здесь: https://msdn.microsoft.com/en-gb/data/jj591583.aspx

IE:

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

Альтернативные ответы

используя аннотацию данные,

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

при помощи отображения

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

Будьте осторожны с этим решением. Добавление атрибута 'Key' в свойство' UserName' приведет к тому, что свойство 'UserName' станет основным ключом в базе данных. Только свойство 'UserId' должно быть помечено атрибутом' Key'. Это решение даст вам «правильное» поведение на стороне программирования, давая вам неправильный дизайн базы данных. –

+4

смешной -10 принят ответ :) –

20

EF не поддерживает уникальные столбцы, кроме ключей. Если вы используете EF Migrations, вы можете заставить EF создать уникальный индекс в столбце UserName (в коде миграции, а не какой-либо аннотации), но уникальность будет применяться только в базе данных. Если вы попытаетесь сохранить дублирующее значение, вам придется поймать исключение (нарушение ограничений), запущенное базой данных.

+1

Это именно то, что я искал! Мне было интересно, можно ли добавлять такие ограничения с помощью миграции. –

+0

@Ladislav Mrnka: Возможно ли это также с помощью метода Seed? –

+1

Забота о предоставлении примера? Благодаря! – Zero3

5

Обратите внимание, что в Entity Framework 6.1 (в настоящее время в бета-версии) поддержка IndexAttribute будет аннотировать свойства индекса, что автоматически приведет к (уникальному) индексу в ваших первых переходах кода.

170

В Entity Framework 6.1+ вы можете использовать этот атрибут модели:

[Index(IsUnique=true)] 

Вы можете найти его в этом пространстве имен:

using System.ComponentModel.DataAnnotations.Schema; 

Если ваша модель поля является строкой, убедитесь, он не установлен на nvarchar (MAX) в SQL Server или вы увидите эту ошибку с Entity Framework Code Сначала:

Столбец 'x' в таблице 'dbo.y' i s типа, который недопустим для использования в качестве ключевого столбца в индексе.

Причина в том, из-за этого:

SQL Server сохраняет ограничение 900 байт, для максимального общего размера всех ключевых столбцов индекса."

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

Вы можете решить эту проблему, установив максимальную длину строки на модели:

[StringLength(450)] 

Ваша модель будет выглядеть, как это сейчас в EF CF 6.1 +:

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

Обновление:

если вы используете Fluent:

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

и использовать в MODELBUILDER:

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

Update 2

для EntityFrameworkCore смотрите также эту тему: https://github.com/aspnet/EntityFrameworkCore/issues/1698

+14

Спасибо за ответ на старое сообщение этого парня с некоторой актуальной текущей информацией! –

+2

Настройка работы StringLength. отличный ответ. – vidriduch

+1

почему индекс, почему не просто ограничение? –

8

Из вашего кода становится очевидным, что вы используете POCO. Не нужен другой ключ: вы можете добавить индекс, как предложено juFo.
Если вы используете Fluent API вместо того, чтобы приписать имя пользователя собственности вашей колонки аннотацию должен выглядеть следующим образом:

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

Это создаст следующий 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] 

При попытке вставить несколько пользователей, имеющих то же самое UserName вы получите DbUpdateException со следующим сообщением:

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

Опять же, столбец annotati в Entity Framework до версии 6.1 недоступны.

Смежные вопросы