visual unity studio remarks net method example description c# entity-framework entity-framework-6 ef-fluent-api

c# - studio - summary unity



¿Estableciendo Restricción única con API fluida? (6)

Estoy intentando construir una Entidad EF con Code First y una EntityTypeConfiguration usando una API fluida. crear claves primarias es fácil, pero no así con una restricción única. Estaba viendo publicaciones antiguas que sugerían ejecutar comandos SQL nativos para esto, pero eso parece frustrar el propósito. ¿Es esto posible con EF6?


Aquí hay 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" }); } }

Src: Creación de índice único con la API de Entity Framework 6.1 con fluidez


Como una adición a la respuesta de Yorro, también se puede hacer mediante el uso de atributos.

Ejemplo de combinación de teclas única de tipo int :

[Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)] public int UniqueKeyIntPart1 { get; set; } [Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)] public int UniqueKeyIntPart2 { get; set; }

Si el tipo de datos es string , se debe agregar el atributo MaxLength :

[Index("IX_UniqueKeyString", IsUnique = true, Order = 1)] [MaxLength(50)] public string UniqueKeyStringPart1 { get; set; } [Index("IX_UniqueKeyString", IsUnique = true, Order = 2)] [MaxLength(50)] public string UniqueKeyStringPart2 { get; set; }

Si hay un problema de separación de modelo de dominio / almacenamiento, el uso de atributo / clase Metadatatype puede ser una opción: https://msdn.microsoft.com/en-us/library/ff664465%28v=pandp.50%29.aspx?f=255&MSPPError=-2147217396

Un ejemplo de aplicación de consola rápida:

using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity; namespace EFIndexTest { class Program { static void Main(string[] args) { using (var context = new AppDbContext()) { var newUser = new User { UniqueKeyIntPart1 = 1, UniqueKeyIntPart2 = 1, UniqueKeyStringPart1 = "A", UniqueKeyStringPart2 = "A" }; context.UserSet.Add(newUser); context.SaveChanges(); } } } [MetadataType(typeof(UserMetadata))] public class User { public int Id { get; set; } public int UniqueKeyIntPart1 { get; set; } public int UniqueKeyIntPart2 { get; set; } public string UniqueKeyStringPart1 { get; set; } public string UniqueKeyStringPart2 { get; set; } } public class UserMetadata { [Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)] public int UniqueKeyIntPart1 { get; set; } [Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)] public int UniqueKeyIntPart2 { get; set; } [Index("IX_UniqueKeyString", IsUnique = true, Order = 1)] [MaxLength(50)] public string UniqueKeyStringPart1 { get; set; } [Index("IX_UniqueKeyString", IsUnique = true, Order = 2)] [MaxLength(50)] public string UniqueKeyStringPart2 { get; set; } } public class AppDbContext : DbContext { public virtual DbSet<User> UserSet { get; set; } } }


En EF6.2 , puede usar HasIndex() para agregar índices para la migración a través de una API fluida.

https://github.com/aspnet/EntityFramework6/issues/274

Ejemplo

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

En EF6.1 en adelante, puede usar IndexAnnotation() para agregar índices para la migración en su API fluida.

http://msdn.microsoft.com/en-us/data/jj591617.aspx#PropertyIndex

Debe agregar referencia a:

using System.Data.Entity.Infrastructure.Annotations;

Ejemplo Básico

Aquí hay un uso simple, agregando un índice en la propiedad User.FirstName

modelBuilder .Entity<User>() .Property(t => t.FirstName) .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));

Ejemplo práctico:

Aquí hay un ejemplo más realista. Agrega un índice único en propiedades múltiples: User.FirstName y User.LastName , con un nombre de índice "IX_FIrstNameLastName"

modelBuilder .Entity<User>() .Property(t => t.FirstName) .IsRequired() .HasMaxLength(60) .HasColumnAnnotation( IndexAnnotation.AnnotationName, new IndexAnnotation( new IndexAttribute("IX_FirstNameLastName", 1) { IsUnique = true })); modelBuilder .Entity<User>() .Property(t => t.LastName) .IsRequired() .HasMaxLength(60) .HasColumnAnnotation( IndexAnnotation.AnnotationName, new IndexAnnotation( new IndexAttribute("IX_FirstNameLastName", 2) { IsUnique = true }));


La respuesta de @coni2k es correcta; sin embargo, debe agregar el atributo [StringLength] para que funcione; de ​​lo contrario, obtendrá una excepción de clave no válida (ejemplo abajo).

[StringLength(65)] [Index("IX_FirstNameLastName", 1, IsUnique = true)] public string FirstName { get; set; } [StringLength(65)] [Index("IX_FirstNameLastName", 2, IsUnique = true)] public string LastName { get; set; }