I have a problem with POCO validation in EF ObjectContext. Problem is as following ...
Project structure:
Domain objects (POCO) in separate Class project (ex. Order and OrderItems)
Repository in separate Class project (EF, UnitOfWork, includes Domain objects)
Website (MVC3 - includes Domain and Repository projects)
(Note: Only the Repository project has any reference to EF)
Order has a collection of OrderItem's (ICollection<T>). "OrderItem" references IValidateObject for model validation (and DataAnnotations).
When i add a OrderItem to Order and save (> EF context.SaveChanges()). Is there any generic way, to validate all objects with ObjectState "Modified" or "Added". It seams like EF isn't executing Validation automatically. EF shouldn't save, if objects (even newly
attached in collection) isn't valid. I could hard-code this with the SavingChanges event on EF ObjectContext, but that's a bad solution IMO.
The problem is, when you add a entity to a property which is based on a collection (and not EF > context.OrderItems.AddObject) ... validation is not handled.
But i think i have found a solution in the meantime. Validation is done when saving via UnitOfWork. Each entity has a IsValid (based on DataAnnotations & IValidatableObject) implemented. So before executing "SaveChanges()" all added, modified entities is validated
- and only Saved if all are valid.
public abstract class BaseEntity
{
#region IValidator Members
public IEnumerable<ValidationResult> GetErrors()
{
ICollection<ValidationResult> validationList = new List<ValidationResult>();
var validatorContext = new ValidationContext(this, null, null);
Validator.TryValidateObject(this, validatorContext, validationList, true);
var validator = this as IValidatableObject;
if (validator != null)
{
foreach (var error in validator.Validate(validatorContext))
validationList.Add(error);
}
return validationList;
}
[ScaffoldColumn(false)]
public bool IsValid
{
get { return !GetErrors().Any(); }
}
#endregion
}
public class UnitOfWork : IDisposable
{
private readonly iJournalContext _context;
public UnitOfWork()
{
_context = new iJournalContext();
_context.SavingChanges += UnitOfWorkSavingChanges;
}
#region SavingChanges Events
protected void UnitOfWorkSavingChanges(object sender, EventArgs e)
{
var changedEnterties = _context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified).Where(c => c.Entity != null);
if (changedEnterties.Any())
{
var currentDate = DateTime.Now;
foreach (ObjectStateEntry entry in changedEnterties.Where(c => c.Entity is IEntity))
{
var entity = entry.Entity as IEntity;
switch (entry.State)
{
case EntityState.Added:
entity.DateCreated = currentDate;
break;
case EntityState.Deleted:
break;
case EntityState.Modified:
break;
}
entity.DateModified = currentDate;
}
foreach (ObjectStateEntry entry in changedEnterties.Where(c => c.Entity is BaseEntity))
{
var entity = entry.Entity as BaseEntity;
if (!entity.IsValid)
{
ValidationResult validationResult = entity.GetErrors().FirstOrDefault();
throw new ValidationException(validationResult, null, null);
}
}
}
}
#endregion
}
mm98
Member
12 Points
2 Posts
Entity Framework 4.1 POCO, Collection Validation
Aug 18, 2011 09:32 PM|LINK
Hi.
I have a problem with POCO validation in EF ObjectContext. Problem is as following ...
Project structure:
(Note: Only the Repository project has any reference to EF)
Order has a collection of OrderItem's (ICollection<T>). "OrderItem" references IValidateObject for model validation (and DataAnnotations).
When i add a OrderItem to Order and save (> EF context.SaveChanges()). Is there any generic way, to validate all objects with ObjectState "Modified" or "Added". It seams like EF isn't executing Validation automatically. EF shouldn't save, if objects (even newly attached in collection) isn't valid. I could hard-code this with the SavingChanges event on EF ObjectContext, but that's a bad solution IMO.
Thanks i advance
Carsten, Denmark
Decker Dong ...
All-Star
118619 Points
18779 Posts
Re: Entity Framework 4.1 POCO, Collection Validation
Aug 20, 2011 03:35 AM|LINK
Hello:)
In fact you can do this:
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
//Do what you want...
}
}
If I understand you wrongly, plz tell me:)
mm98
Member
12 Points
2 Posts
Re: Entity Framework 4.1 POCO, Collection Validation
Aug 20, 2011 07:20 AM|LINK
Hi.
The problem is, when you add a entity to a property which is based on a collection (and not EF > context.OrderItems.AddObject) ... validation is not handled.
But i think i have found a solution in the meantime. Validation is done when saving via UnitOfWork. Each entity has a IsValid (based on DataAnnotations & IValidatableObject) implemented. So before executing "SaveChanges()" all added, modified entities is validated - and only Saved if all are valid.
public abstract class BaseEntity { #region IValidator Members public IEnumerable<ValidationResult> GetErrors() { ICollection<ValidationResult> validationList = new List<ValidationResult>(); var validatorContext = new ValidationContext(this, null, null); Validator.TryValidateObject(this, validatorContext, validationList, true); var validator = this as IValidatableObject; if (validator != null) { foreach (var error in validator.Validate(validatorContext)) validationList.Add(error); } return validationList; } [ScaffoldColumn(false)] public bool IsValid { get { return !GetErrors().Any(); } } #endregion }public class UnitOfWork : IDisposable { private readonly iJournalContext _context; public UnitOfWork() { _context = new iJournalContext(); _context.SavingChanges += UnitOfWorkSavingChanges; } #region SavingChanges Events protected void UnitOfWorkSavingChanges(object sender, EventArgs e) { var changedEnterties = _context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified).Where(c => c.Entity != null); if (changedEnterties.Any()) { var currentDate = DateTime.Now; foreach (ObjectStateEntry entry in changedEnterties.Where(c => c.Entity is IEntity)) { var entity = entry.Entity as IEntity; switch (entry.State) { case EntityState.Added: entity.DateCreated = currentDate; break; case EntityState.Deleted: break; case EntityState.Modified: break; } entity.DateModified = currentDate; } foreach (ObjectStateEntry entry in changedEnterties.Where(c => c.Entity is BaseEntity)) { var entity = entry.Entity as BaseEntity; if (!entity.IsValid) { ValidationResult validationResult = entity.GetErrors().FirstOrDefault(); throw new ValidationException(validationResult, null, null); } } } } #endregion }