c# - foreign - Creación de índice único con la API de Entity Framework 6.1 con fluidez
unique entity framework core (6)
En la nueva versión de EF que es 6.2 , puede usar el método HasIndex
:
modelBuilder.Entity<User>().HasIndex(user => user.Email).IsUnique(true);
modelBuilder.Entity<User>().HasIndex(user => user.UserName).IsUnique(true);
Actualización para EF Core:
modelBuilder.Entity<User>()
.HasIndex(b => b.Email)
.IsUnique();
modelBuilder.Entity<User>()
.HasIndex(b => b.UserName)
.IsUnique();
Tengo una columna "Nombre" que debe estar separada. Sin clave foránea ni nada de eso.
EF 6.1 finalmente admite la creación de tales índices a través de Anotaciones. Eso ya se ha discutido en SO. Pero parece que solo se puede hacer a través de anotaciones en las clases. ¿Cómo hago eso usando solo la API Fluent?
Algo como esto:
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(); //???
}
}
Esta respuesta contiene solo información adicional ya que hay respuestas excelentes.
Si desea tener múltiples campos únicos en su índice, puede lograrlo agregando la propiedad Order
. También debe asegurarse de usar el mismo nombre de índice en todas sus propiedades (consulte uniqueIndex
continuación).
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
}
)
);
Ahora, digamos que también quiere un índice en PropertyTwo
.
La forma incorrecta de hacerlo sería comenzar una nueva línea con this.Property(t => t.PropertyTwo)
ya que CANCELARía su índice único.
Todos sus índices (índice y único) se deben definir al mismo tiempo. Esta sería la forma correcta de hacerlo:
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
}
}
)
);
Finalmente, si también desea cambiar el orden de clasificación de su índice / único, puede ver:
¿Cómo agregar un índice en múltiples columnas con clasificación ASC / DESC usando la API Fluent? .
Para mí, usando MVC 5 y EF 6, el punto clave era especificar una longitud en la propiedad de cadena donde quería colocar el índice.
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); }
Puede crear un índice único en su archivo de migración.
En el Administrador de paquetes:
- Habilitar migraciones
- Add-Migration InitialMigration
Esto creará un nuevo archivo en su carpeta Migrations que tiene marca de tiempo. La clase tendrá un método Arriba y Abajo que puede usar para crear el índice:
public override void Up()
{
// ...
CreateIndex("tableName", "columnName", unique: true, name: "myIndex");
}
public override void Down()
{
// ...
DropIndex("tableName", "myIndex");
}
Para ejecutar la migración escriba Update-Database en el administrador de paquetes.
También puede agregar el índice como parte de la migración que también crea la tabla:
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);
Según la respuesta de Anatolii, este es un método de extensión para establecer índices únicos con más fluidez:
public static class MappingExtensions
{
public static PrimitivePropertyConfiguration IsUnique(this PrimitivePropertyConfiguration configuration)
{
return configuration.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }));
}
}
Uso:
modelBuilder
.Entity<Person>()
.Property(t => t.Name)
.IsUnique();
Generará migración como:
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" });
}
}
NOTA: relevante para EF 6
Puede usar IndexAttribute
como se mencionó pero con DataAnnotations
Fluent API
lugar de DataAnnotations
que hará el truco:
modelBuilder
.Entity<Person>()
.Property(t => t.Name)
.HasColumnAnnotation(
"Index",
new IndexAnnotation(new IndexAttribute("IX_Name") { IsUnique = true }));
Lamentablemente, no hay otra manera de crear índices únicos utilizando la Fluent API
. Existe un problema abierto con respecto a esta característica: Restricciones únicas (Índices únicos)
En la última versión de EF Core puede confiar en la
Fluent API
para especificar índices sin trucos adicionales. HasIndex
permite definirlo: modelBuilder
.Entity<Person>()
.HasIndex(x => x.Name);
Por lo tanto, retoma el objeto IndexBuilder
, puede usarlo para otras configuraciones de índice (es decir, unicidad):
modelBuilder
.Entity<Person>()
.HasIndex(x => x.Name)
.IsUnique();