Первый уникальный столбец Entity Framework
Я использую Entity Framework 4.3 и используя Code Fist.
У меня есть класс
public class User
{
public int UserId{get;set;}
public string UserName{get;set;}
}
Как сообщить Entity Framework, что UserName должно быть уникальным при создании таблицы базы данных?
Я предпочел бы использовать аномалии данных вместо файла конфигурации, если это возможно.
Ответы
Ответ 1
Решение для 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;}
Альтернативные ответы
с использованием аннотации данных
[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");
Ответ 2
В Entity Framework 6. 1+ вы можете использовать этот атрибут в вашей модели:
[Index(IsUnique=true)]
Вы можете найти его в этом пространстве имен:
using System.ComponentModel.DataAnnotations.Schema;
Если в качестве поля модели используется строка, убедитесь, что в SQL Server не установлено значение nvarchar (MAX), иначе вы увидите эту ошибку в коде Entity Framework 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;}
}
Обновление:
если вы используете свободно:
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());
// ...
}
Обновление 2
для EntityFrameworkCore см. также эту тему: https://github.com/aspnet/EntityFrameworkCore/issues/1698
Обновление 3
для EF6.2 см.: https://github.com/aspnet/EntityFramework6/issues/274
Обновление 4
ASP.NET Core Mvc 2.2 с EF Core:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Unique { get; set; }
Ответ 3
EF не поддерживает уникальные столбцы, кроме ключей. Если вы используете EF Migrations, вы можете заставить EF создать уникальный индекс в столбце UserName
(в коде миграции, а не какой-либо аннотации), но уникальность будет применяться только в базе данных. Если вы попытаетесь сохранить дублирующее значение, вам придется поймать исключение (нарушение ограничений), запущенное базой данных.
Ответ 4
Из вашего кода становится очевидным, что вы используете POCO. Отсутствует другой ключ: вы можете добавить индекс, как предлагается juFo.
Если вы используете Fluent API вместо атрибута UserName, ваша аннотация столбца должна выглядеть так:
this.Property(p => p.UserName)
.HasColumnAnnotation("Index", new IndexAnnotation(new[] {
new IndexAttribute("Index") { IsUnique = true }
}
));
Это создаст следующий SQL script:
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.
И снова аннотации столбцов недоступны в Entity Framework до версии 6.1.
Ответ 5
Обратите внимание, что в Entity Framework 6.1 (в настоящее время в бета-версии) поддержка IndexAttribute будет аннотировать свойства индекса, которые автоматически приведут к (уникальному) индексу в ваших первых переходах кода.
Ответ 6
В EF 6.2 с использованием FluentAPI вы можете использовать HasIndex()
modelBuilder.Entity<User>().HasIndex(u => u.UserName).IsUnique();