实体框架代码第一个唯一列

我正在使用实体框架4.3和代码拳。

我还有课

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

在创建数据库表时,如何告诉实体框架 UserName 必须是唯一的? 如果可能的话,我希望使用数据注释代替配置文件。

152075 次浏览

EF 不支持键以外的唯一列。如果您正在使用 EF 迁移,您可以强制 EF 在 UserName列上创建唯一索引(在迁移代码中,而不是通过任何注释) ,但是唯一性将仅在数据库中强制执行。如果尝试保存重复值,则必须捕获由数据库触发的异常(违反约束)。

EF4.3的解决方案

唯一用户名

在列上添加数据注释,如下所示:

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

唯一身份证 , 我在我的专栏上增加了装饰[关键词]。 这里描述的解决方案相同: < a href = “ https://msdn.microsoft.com/en-gb/data/jj591583.aspx”rel = “ nofollow norefrer”> 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");

请注意,在实体框架6.1(目前处于测试阶段)中,将支持 IndexAttribute 对索引属性进行注释,这将自动在代码首次迁移中生成(唯一)索引。

在实体框架6.1 + 中,你可以在你的模型上使用这个属性:

[Index(IsUnique=true)]

您可以在这个名称空间中找到它:

using System.ComponentModel.DataAnnotations.Schema;

如果您的模型字段是一个字符串,请确保在 SQLServer 中没有将其设置为 nvarchar (MAX) ,否则您将在实体框架代码优先级中看到此错误:

表“ dbo.y”中的“ x”列的类型对于用作索引中的键列是无效的。

原因是这样的:

SQLServer 保留了所有索引键列的最大总大小的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 } }));
}
}

并在您的 model Builder 中使用:

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

NET 核心 Mvc 2.2与 EF 核心:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Unique { get; set; }

从您的代码中可以很明显地看出,您使用的是 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.

同样,列注释在6.1版之前的实体框架中是不可用的。

在使用 FluentAPI 的 EF 6.2中,可以使用 HasIndex()

modelBuilder.Entity<User>().HasIndex(u => u.UserName).IsUnique();