Первый уникальный столбец Entity Framework
Я использую Entity Framework 4.3 и используя Code Fist.
У меня есть class
public class User { public int UserId{get;set;} public string UserName{get;set;} }
Как сообщить Entity Framework, что UserName должно быть уникальным при создании таблицы базы данных? Я предпочел бы вместо использования файла конфигурации использовать anotations данных, если это возможно.
В Entity Framework 6.1+ вы можете использовать этот атрибут в своей модели:
[Index(IsUnique=true)]
Вы можете найти его в этом пространстве имен:
using System.ComponentModel.DataAnnotations.Schema;
Если ваше поле модели является строкой, убедитесь, что оно не установлено в nvarchar (MAX) в SQL Server или вы увидите эту ошибку с Entity Framework Code First:
Столбец «x» в таблице «dbo.y» имеет тип, который недопустим для использования в качестве ключевого столбца в индексе.
Причина в том, что:
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 { 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()); // ... }
Обновление 2
для EntityFrameworkCore см. также эту тему: https://github.com/aspnet/EntityFrameworkCore/issues/1698
Обновление 3
для EF6.2 см. https://github.com/aspnet/EntityFramework6/issues/274
EF не поддерживает уникальные столбцы, кроме ключей. Если вы используете EF Migrations, вы можете заставить EF создать уникальный индекс в столбце UserName
(в коде миграции, а не какой-либо annotations), но уникальность будет применяться только в базе данных. Если вы попытаетесь сохранить дублирующее значение, вам придется поймать исключение (нарушение ограничений), запущенное базой данных.
Из вашего кода становится очевидным, что вы используете POCO. Наличие другого ключа не требуется: вы можете добавить индекс, как было предложено juFo .
Если вы используете Fluent API вместо атрибута UserName, ваша аннотация столбца должна выглядеть так:
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]
Если вы попытаетесь вставить несколько пользователей с одинаковым именем пользователя, вы получите исключение DbUpdateException со следующим сообщением:
Cannot insert duplicate key row in object 'dbo.Users' with unique index 'Index'. The duplicate key value is (...). The statement has been terminated.
Опять же, annotations столбцов недоступны в Entity Framework до версии 6.1.
Обратите внимание, что в Entity Framework 6.1 (в настоящее время в бета-версии) поддержка IndexAttribute будет аннотировать свойства индекса, что автоматически приведет к (уникальному) индексу в ваших первых переходах кода.
Решение для EF4.3
Уникальное имя пользователя
Добавьте аннотацию данных к столбцу как:
[Index(IsUnique = true)] [MaxLength(255)] // for code-first implementations public string UserName{get;set;}
Уникальный идентификатор , я добавил украшение [Key] над моей колонкой и сделал. Такое же решение, как описано здесь: https://msdn.microsoft.com/en-gb/data/jj591583.aspx
IE:
[Key] public int UserId{get;set;}
Альтернативные ответы
с использованием annotations данных
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] [Column("UserId")]
использование картографирования
mb.Entity() .HasKey(i => i.UserId); mb.User () .Property(i => i.UserId) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) .HasColumnName("UserId");