Existe otra manera más fácil para realizar validaciones personalizadas a nuestras tablas utilizando las clases proporcionadas por .NET
Puedes crear tus reglas personalizadas creando una clase que herede de la clase ValidationAttribute e implementar el método IsValid esta función recibe 2 parámetros un objeto llamado value que contiene el valor del campo que queremos validar y un objeto validationContext que nos sirve para manejar la validación de la regla.
Agregamos un índice único a nuestra tabla producto, en nuestra carpeta Models luego Entity Configurations luego nuestro archivo ProductoConfiguration.cs
ProductoConfiguration.cs
publicclassProductoConfiguration:IEntityTypeConfiguration<Producto>{publicvoidConfigure(EntityTypeBuilder<Producto> builder) { //Código indice para el nombre en productobuilder.HasIndex(e =>e.Nombre) .IsUnique() .HasName("UX_ProductoNombre"); }}
Creamos la migración y actualizamos nuestra base de datos
En nuestra clase productoDAO agregamos una función para validar que el nombre del producto no se repita, recibe como parámetros el Id del producto y el nombre del producto
En nuestra carpeta Rules > Producto creamos una nueva clase NombreValidation.cs que hereda de la clase ValidationAttribute y sobrescribimos el método ValidationResult
NombreValidation.cs
publicclassNombreValidation:ValidationAttribute{ protectedoverrideValidationResultIsValid(object value,ValidationContext validationContext) { //Obtenemos el contexto de nuestra aplicaciónvar contexto = (CaducaContext)validationContext .GetService(typeof(CaducaContext)); //Obtenemos la clase para personalizar los mensajes de //error por idiomavar localizacion = (LocService)validationContext .GetService(typeof(LocService)); //Obtenemos el producto a agregar/modificarProducto producto = (Producto)validationContext .ObjectInstance; ProductoDAO productoDAO =newProductoDAO(contexto, localizacion); //En lugar de producto.Nombre también puedes pasar //value.toString() el cual contiene el valor del campo //a validarif (productoDAO.EsNombreRepetido(producto.Id,producto.Nombre)) { //Si el producto esta repetido regresamos el //mensaje de errorreturnnewValidationResult(productoDAO.customError .Message); } //Indica que la regla se cumple correctamentereturnValidationResult.Success; }}
Quitamos el código para validar el nombre de nuestra clase ProductoDAO
A nuestra clase Producto.cs le agregamos la validación
Producto.cs
publicclassProducto{ //..... Los demás campos de tu tabla producto van aqui [NombreValidation()]publicstring Nombre { get; set; }}
Esta forma es más sencilla que la anterior. Como ejercicio puedes agregar la validación para la clave repetida.
Puedes pasar como parámetro el nombre de algún campo adicional que necesites, por ejemplo
Producto.cs
publicclassProducto{ //..... Los demás campos de tu tabla producto van aqui [NombreValidation("Id")]publicstring Nombre { get; set; }}
NombreValidation.cs
publicclassNombreValidation:ValidationAttribute{string campoAdicional;publicNombreValidation(string campoAdicional) {this.campoAdicional= campoAdicional; }protectedoverrideValidationResultIsValid(object value,ValidationContext validationContext) { //...códigovar campo =validationContext.ObjectType.GetProperty( campoAdicional);if (campo ==null)thrownewArgumentException("Propiedad no encontrada");var id = (int)campo.GetValue(validationContext.ObjectInstance); //...código }}
Ejercicio de práctica
Agrega un índice y la validación para el campo clave, puedes comparar tu solución con mi código en github.