Las Data Annotations son un conjunto de atributos predefinidos que se utilizan en C# para aplicar configuraciones específicas a las propiedades de las clases.
Estos atributos ayudan a configurar cómo deben ser tratadas las entidades y propiedades de nuestro modelo, al ser mapeadas a las tablas y columnas de la base de datos.
Por ejemplo, nos permiten definir propiedades como claves primarias, campos requeridos, longitudes máximas de texto, y más.
Como cualquier otro atributo, para aplicarlo simplemente tendremos que ponerlo delante de la clase o propiedad que queramos modificar.
Están disponibles en System.ComponentModel.DataAnnotations
, por lo que tendréis que añadir el namespace.
Principales Data Annotations
Vamos a ver algunas de las Data Annotation más importantes de Entity Framework, y cómo usar cada una de ellas.
Configuración de tablas y columnas
El atributo [Table]
especifica el nombre de la tabla asociada con una entidad
[Table("Productos")]
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
El atributo [Column]
permite especificar el nombre de la columna en la base de datos que corresponde a una propiedad.
public class Student
{
public int StudentId { get; set; }
[Column("Full_Name")] // Mapea la propiedad "Name" a la columna "Full_Name"
public string Name { get; set; }
}
El atributo [DataType]
permite especificar el tipo de datos de una propiedad.
public class Student
{
public int StudentId { get; set; }
[DataType(DataType.EmailAddress)] // Especifica que esta propiedad debe ser una dirección de correo electrónico
public string Email { get; set; }
}
Configuración de claves
El atributo [Key]
se utiliza para marcar una propiedad como clave primaria de la entidad.
public class Student
{
[Key] // Marca esta propiedad como clave primaria
public int StudentId { get; set; }
public string Name { get; set; }
}
El atributo [DatabaseGenerated]
controla cómo se generan los valores de una propiedad en la base de datos. Es especialmente útil para campos autoincrementales, valores calculados o fechas generadas automáticamente.
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; } // Se genera automáticamente al insertar (IDENTITY)
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime LastUpdated { get; set; } // Lo calcula la base de datos (ej: GETDATE())
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string ProductCode { get; set; } // No se genera automáticamente (valor manual)
}
Validación y restricciones
El atributo [Required]
se utiliza para indicar que una propiedad no puede ser nula en la base de datos. Es similar a la restricción NOT NULL
en SQL.
public class Student
{
public int StudentId { get; set; }
[Required] // Indica que el nombre es obligatorio
public string Name { get; set; }
}
El atributo [MaxLength]
permiten establecer un límite para la longitud de una cadena de texto.
public class Product
{
[MaxLength(100)]
public string Name { get; set; } // NVARCHAR(100)
}
Si intentas guardar una cadena de texto que exceda los 100 caracteres, EF Core rechazará la operación.
El atributo [StringLength]
define una longitud máxima y opcionalmente una mínima,
[StringLength(50, MinimumLength = 3)]
public string ShortDescription { get; set; }
El atributo [Range]
se utiliza para especificar un rango de valores válidos para una propiedad numérica.
public class Course
{
public int CourseId { get; set; }
[Range(1, 10)] // El rango de valores permitidos para el número de créditos
public int Credits { get; set; }
}
Configuración de relaciones
El atributo [ForeignKey]
se utiliza para establecer una relación entre dos entidades. En este caso, se puede usar para especificar que una propiedad es una clave foránea que se refiere a otra entidad.
public class Enrollment
{
public int EnrollmentId { get; set; }
[ForeignKey("Student")] // Establece la relación con la entidad Student
public int StudentId { get; set; }
public Student Student { get; set; } // Propiedad de navegación
}
Este atributo permite que EF Core sepa que StudentId
es una clave foránea que hace referencia a la tabla Student
.
El atributo [InverseProperty]
se utiliza para especificar la propiedad de navegación inversa en una relación entre dos entidades.
Esto es útil cuando hay múltiples relaciones entre las mismas entidades y EF Core necesita ayuda para determinar cómo se relacionan.
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
[InverseProperty("Student")] // Establece la propiedad de navegación inversa
public ICollection<Enrollment> Enrollments { get; set; }
}
Este atributo le indica a EF Core que la propiedad Enrollments
en Student
es la inversa de la propiedad Student
en Enrollment
, evitando ambigüedades en el mapeo de relaciones.
Ejemplo completo
Vamos a verlo con un ejemplo completo, de cómo podría ser el modelo de datos de un blog muy simple, que solo tuviera Author y Posts.
[Table("BlogPosts")]
public class Post
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PostId { get; set; }
[Required]
[MaxLength(200)]
public string Title { get; set; }
[Column("Contenido", TypeName = "nvarchar(max)")]
public string Content { get; set; }
[ForeignKey("Author")]
public int AuthorId { get; set; }
public Author Author { get; set; }
public ICollection<Comment> Comments { get; set; }
}
[Table("Autores")]
public class Author
{
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
[InverseProperty("Author")]
public ICollection<Post> Posts { get; set; }
}
Aquí se ve muy bien los puntos fuertes y débiles de las Data Annotations. Es sencillo y cómodo, pero “ensucia” mucho nuestros objetos