我正在使用 Entity Framework 4.3 并使用 Code Fist。
我有一堂课
public class User
{
public int UserId{get;set;}
public string UserName{get;set;}
}
创建数据库表时,如何告诉 Entity Framework UserName 必须是唯一的?如果可能的话,我更喜欢使用数据注释而不是配置文件。
在 Entity Framework 6.1+ 中,您可以在模型上使用此属性:
[Index(IsUnique=true)]
您可以在此命名空间中找到它:
using System.ComponentModel.DataAnnotations.Schema;
如果您的模型字段是字符串,请确保在 SQL Server 中未将其设置为 nvarchar(MAX),否则您将在 Entity Framework Code First 中看到此错误:
表 'dbo.y' 中的列 'x' 的类型不能用作索引中的键列。
原因是这样的:
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 } }));
}
}
并在您的模型构建器中使用:
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
带有 EF Core 的 ASP.NET Core Mvc 2.2:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Unique { get; set; }
EF 不支持键以外的唯一列。如果您使用 EF 迁移,您可以强制 EF 在 UserName
列上创建唯一索引(在迁移代码中,而不是通过任何注释),但唯一性将仅在数据库中强制执行。如果您尝试保存重复值,您将不得不捕获由数据库触发的异常(违反约束)。
在使用 FluentAPI 的 EF 6.2 中,您可以使用 HasIndex()
modelBuilder.Entity<User>().HasIndex(u => u.UserName).IsUnique();
从您的代码中可以明显看出您使用的是 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]
如果您尝试插入具有相同 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.
同样,列注释在 6.1 版之前的实体框架中不可用。
请注意,在 Entity Framework 6.1(当前处于测试阶段)中,将支持 IndexAttribute 来注释索引属性,这将自动在您的 Code First 迁移中生成(唯一)索引。
EF4.3 解决方案
唯一用户名
在列上添加数据注释:
[Index(IsUnique = true)]
[MaxLength(255)] // for code-first implementations
public string UserName{get;set;}
唯一 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");
Key
属性添加到 UserName
属性将导致 UserName
属性成为数据库中的主键。只有 UserId
属性应使用 Key
属性进行标记。该解决方案将为您提供编程方面的“正确”行为,同时为您提供不正确的数据库设计。
不定期副业成功案例分享
"There are no significant differences between creating a UNIQUE constraint and creating a unique index that is independent of a constraint. Data validation occurs in the same manner, and the query optimizer does not differentiate between a unique index created by a constraint or manually created. However, creating a UNIQUE constraint on the column makes the objective of the index clear."
msdn.microsoft.com/en-us/library/ms187019.aspx[Index(propertyNames: nameof(UserName), IsUnique = true)] public class User { public int UserId{get;set;} [StringLength(450)] public string UserName{get;set;} }