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

cpo*_*ign 108 entity-framework data-annotations entity-framework-4.3

我正在使用Entity Framework 4.3并使用Code Fist.

我上课了

public class User
{
   public int UserId{get;set;}
   public string UserName{get;set;}
}
Run Code Online (Sandbox Code Playgroud)

在创建数据库表时,如何告诉Entity Framework UserName必须是唯一的?如果可能的话,我更愿意使用数据anotations而不是配置文件.

juF*_*uFo 236

在Entity Framework 6.1+中,您可以在模型上使用此属性:

[Index(IsUnique=true)]
Run Code Online (Sandbox Code Playgroud)

您可以在此命名空间中找到它:

using System.ComponentModel.DataAnnotations.Schema;
Run Code Online (Sandbox Code Playgroud)

如果您的模型字段是字符串,请确保它在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)]
Run Code Online (Sandbox Code Playgroud)

您的模型现在将在EF CF 6.1+中显示如下:

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

更新:

如果您使用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 } }));
    }
  }
Run Code Online (Sandbox Code Playgroud)

并在你的modelBuilder中使用:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  // ...
  modelBuilder.Configurations.Add(new UserMap());
  // ...
}
Run Code Online (Sandbox Code Playgroud)

更新2

for 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; }
Run Code Online (Sandbox Code Playgroud)

  • 感谢您回复此家伙的旧帖子,其中包含一些相关的当前信息! (20认同)
  • 在 EntityFrameworkCore 中,它是这样完成的: `[Index(propertyNames: nameof(UserName), IsUnique = true)] public class User { public int UserId{get;set;} [StringLength(450)] public string UserName{get;set; } }` (4认同)
  • 注意; 在Entity Framework Core 1.0.0-preview2-final中,数据注释方法不可用 - https://docs.efproject.net/en/latest/modeling/indexes.html#data-annotations (3认同)
  • 设置StringLength工作.很好的答案. (2认同)
  • 为什么一个指数,为什么不只是一个约束? (2认同)
  • 要回答索引与约束的问题...MSDN:`“创建 UNIQUE 约束和创建独立于约束的唯一索引之间没有显着差异。数据验证以相同的方式发生,查询优化器不会区分由约束创建的唯一索引或手动创建的唯一索引。但是,在列上创建 UNIQUE 约束会使索引的目标变得清晰。"` https://msdn.microsoft.com/en-us/library/ms187019。 aspx (2认同)

Lad*_*nka 25

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

  • 注意提供一个例子?谢谢! (2认同)

Ana*_*ish 20

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

modelBuilder.Entity<User>().HasIndex(u => u.UserName).IsUnique();
Run Code Online (Sandbox Code Playgroud)


Ale*_*tov 9

从您的代码中可以看出您使用POCO.拥有另一个密钥是不必要的:您可以按照juFo的建议添加索引.
如果您使用Fluent API而不是归因于UserName属性,则列注释应如下所示:

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

这将创建以下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]
Run Code Online (Sandbox Code Playgroud)

如果您尝试插入具有相同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.
Run Code Online (Sandbox Code Playgroud)

同样,在版本6.1之前的实体框架中不能使用列注释.


Rob*_*bba 5

请注意,在Entity Framework 6.1(目前处于测试阶段)将支持IndexAttribute来注释索引属性,这将自动导致Code First Migrations中的(唯一)索引.


cpo*_*ign -11

EF4.3的解决方案

唯一的用户名

在列上添加数据注释:

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

唯一ID ,我在我的专栏上添加了装饰[Key]并完成。与此处描述的解决方案相同:https ://msdn.microsoft.com/en-gb/data/jj591583.aspx

IE:

[Key]
public int UserId{get;set;}
Run Code Online (Sandbox Code Playgroud)

替代答案

使用数据注释

[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("UserId")]
Run Code Online (Sandbox Code Playgroud)

使用映射

  mb.Entity<User>()
            .HasKey(i => i.UserId);
        mb.User<User>()
          .Property(i => i.UserId)
          .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
          .HasColumnName("UserId");
Run Code Online (Sandbox Code Playgroud)

  • 请小心使用此解决方案。将“Key”属性添加到“UserName”属性将使“UserName”属性成为数据库中的主键。只有“UserId”属性应使用“Key”属性进行标记。该解决方案将为您提供编程方面的“正确”行为,同时为您提供不正确的数据库设计。 (29认同)