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; }
Lamentablemente, esto no es compatible con Entity Framework. Estaba en la hoja de ruta para EF 6, pero se retrasó: Workitem 299: Restricciones únicas (Índices únicos)
Mientras tanto, hay esto:
Lo siento por no copiar el código, es un poco largo.