I want to validate the graph of objects (from different but related entities) being saved with Entity Framework Core. In Entity Framework 6, the framework validates it at SaveChanges Operation. In EF Core, the docs says the validation is not performed automatically. So, in ASP MVC Core, we can use the ModelState.IsValid. But, i'm not using ASP MVC and i prefer to not depend on that very big framework.
Anyway, How I can validate models before SaveChanges in EntityFramework Core 2, without depending on full ASP MVC framework?
Entity Framework provides a great variety of validation features that can feed through to a user interface for client-side validation or be used for server-side validation. When using code first, you can specify validations using annotation or fluent API configurations.
What does the DbContext SaveChanges () method return? Returns. The number of state entries written to the underlying database. This can include state entries for entities and/or relationships.
In Entity Framework, the SaveChanges() method internally creates a transaction and wraps all INSERT, UPDATE and DELETE operations under it. Multiple SaveChanges() calls, create separate transactions, perform CRUD operations and then commit each transaction. The following example demonstrates this.
Yeah, looks like there is no out of the box validation. You can handle it by yourself by overriding SaveChanges
:
public class MyContext : DbContext
{
public virtual DbSet<Model> Models { get; set; }
public MyContext()
{
}
public override int SaveChanges()
{
var changedEntities = ChangeTracker
.Entries()
.Where(_ => _.State == EntityState.Added ||
_.State == EntityState.Modified);
var errors = new List<ValidationResult>(); // all errors are here
foreach (var e in changedEntities)
{
var vc = new ValidationContext(e.Entity, null, null);
Validator.TryValidateObject(
e.Entity, vc, errors, validateAllProperties: true);
}
return base.SaveChanges();
}
}
public class Model
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(32)]
public string Field { get; set; }
[Range(15, 25)]
public int RangeField { get; set; }
}
validateAllProperties
is important because without it you
won't get range validations.SaveChangesAsync
.This thing won't be really helpful if you set constraints with fluent syntax
, unfortunately. Actually, as fluent syntax
can possibly not only add new constraints, but also override existing, it's better to switch completely to attributes annotation, or find another way to make validation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With