使用Entity Framework 6.1流畅的API创建唯一索引

时间:2014-05-27 14:49:37

标签: c# .net entity-framework entity-framework-6 fluent-interface

我有一个专栏"姓名"那一定是独一无二的。没有外国钥匙或类似的东西。

EF 6.1最终支持通过Annotations创建这样的索引。已在SO上讨论过这个问题。但它似乎只能通过类中的注释来完成。如何仅使用Fluent API执行此操作?

这样的事情:

public class PersonConfiguration : EntityTypeConfiguration<Person>
{
    public PersonConfiguration()
    {
        HasKey(p => p.Id);
        Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        //not possible?
        Index(p => p.Name).IsUnique();  //???
    }
}

6 个答案:

答案 0 :(得分:58)

注意:与EF 6相关

您可以按照提及的IndexAttribute使用with Fluent API代替DataAnnotations,这样可以解决问题:

modelBuilder 
    .Entity<Person>() 
    .Property(t => t.Name) 
    .HasColumnAnnotation( 
        "Index",  
        new IndexAnnotation(new IndexAttribute("IX_Name") { IsUnique = true }));

不幸的是,没有其他方法可以使用Fluent API创建唯一索引。关于此功能存在未解决的问题:Unique Constraints (Unique Indexes)

<小时/> 更新:实体框架核心

在最新的EF Core版本中,您可以依赖Fluent API to specify indexes而无需其他技巧。
HasIndex允许定义它:

modelBuilder 
    .Entity<Person>()
    .HasIndex(x => x.Name);

因此,它可以使用IndexBuilder对象来进行进一步的索引配置(即唯一性):

modelBuilder 
    .Entity<Person>()
    .HasIndex(x => x.Name)
    .IsUnique();

答案 1 :(得分:36)

根据Anatolii的回答,这里有一个更流利地设置唯一索引的扩展方法:

public static class MappingExtensions
{
    public static PrimitivePropertyConfiguration IsUnique(this PrimitivePropertyConfiguration configuration)
    {
        return configuration.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }));
    }
}

用法:

modelBuilder 
    .Entity<Person>() 
    .Property(t => t.Name)
    .IsUnique();

将生成迁移,例如:

public partial class Add_unique_index : DbMigration
{
    public override void Up()
    {
        CreateIndex("dbo.Person", "Name", unique: true);
    }

    public override void Down()
    {
        DropIndex("dbo.Person", new[] { "Name" });
    }
}

答案 2 :(得分:28)

这个答案仅包含其他信息,因为已有很好的答案。

如果您希望在索引中包含多个唯一字段,则可以通过添加Order属性来实现。您还必须确保在所有属性中使用相同的索引名称(请参阅下面的uniqueIndex)。

string uniqueIndex = "UN_TableName";

this.Property(t => t.PropertyOne)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(
            new IndexAttribute(uniqueIndex)
            {
                IsUnique = true,
                Order = 1
            }
        )
    );

this.Property(t => t.PropertyTwo)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(
            new IndexAttribute(uniqueIndex)
            {
                IsUnique = true,
                Order = 2
            }

        )
    );

现在,假设您还需要PropertyTwo上的索引。

错误的 这样做的方法是使用this.Property(t => t.PropertyTwo)启动 new 行,因为它会取消您的唯一索引

必须同时定义所有索引(索引和唯一索引)。这将是正确的方法:

this.Property(t => t.PropertyTwo)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(new[] 
            {
                new IndexAttribute(), // This is the index
                new IndexAttribute(uniqueIndex) // This is the Unique made earlier
                {
                    IsUnique = true,
                    Order = 2
                }
            }
        )
    );

最后,如果您还想更改索引/唯一的排序顺序,可以看到:

How to add an index on multiple columns with ASC/DESC sort using the Fluent API ?

答案 3 :(得分:8)

6.2 的新版EF中,您可以使用$assocDataArray[] = [ "First Name" => $fname ,"Last Name" => $lname ,"Email" => $email ]; 方法:

HasIndex

更新EF Core:

 modelBuilder.Entity<User>().HasIndex(user => user.Email).IsUnique(true);
 modelBuilder.Entity<User>().HasIndex(user => user.UserName).IsUnique(true);

Microsoft Docs - EF Core Indexes

答案 4 :(得分:4)

您可以在迁移文件中创建唯一索引。

在包管理器中:

  1. 启用-迁移
  2. Add-Migration InitialMigration
  3. 这将在Migrations文件夹中创建一个带时间戳的新文件。该类将具有可用于创建索引的Up和Down方法:

    public override void Up()
    {
        // ... 
        CreateIndex("tableName", "columnName", unique: true, name: "myIndex");
    }
    
    public override void Down()
    {
        // ...
        DropIndex("tableName", "myIndex");
    }
    

    在程序包管理器中运行迁移类型Update-Database。

    您还可以将索引添加为创建表的迁移的一部分:

    CreateTable(
        "dbo.Products",
        c => new
            {
                ProductId = c.Int(nullable: false, identity: true),
                ProductName = c.String(nullable: false, maxLength: 256),
            })
        .Index(c => c.ProductName, name: "IX_Products_ProductName", unique: true)
        .PrimaryKey(t => t.ProductId);
    

答案 5 :(得分:0)

对我来说,使用MVC 5和EF 6,关键是要在要放置索引的字符串属性上指定长度。

protected override void OnModelCreating(DbModelBuilder modelBuilder){
    //More stuff
    modelBuilder.Entity<Device>().Property(c => c.Name).HasColumnType("nvarchar").HasMaxLength(50);
    modelBuilder.Entity<Device>().HasIndex(c => c.Name).IsUnique(true); 
}