Entity Framework validation with partial updates

I had this issue today, basically Entity Framework always validate all the entity, so if you want to make a partial update using Attach/Entity State way, you can’t do it if you have configured validation on your model and you don’t fill all your entity with good values, but we want to do a partial update without do another query before, and also without filling up all the entity with data I don’t have, so how to do it?

The most easiest and fastest way is to completely disable the validation for your operation, but this is not the ideal way, what about validating the property I’m near to udpate?

using (var db = new NorthwindDbContext())
{
    // disable the validation for this operation
    db.Configuration.ValidateOnSaveEnabled = false;

    var customer = new Customer
    {
        CustomerId = "ALFKI"
    };
    db.Customers.Attach(customer);

    customer.PostalCode = "123456789000";

    // throw sql exception because PostalCode goes over 10 chars maximum
    // String or binary data would be truncated.
    await db.SaveChangesAsync();
}

Thanks to Shimmy I found what I think is the most elegant solution:

protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
    var result = base.ValidateEntity(entityEntry, items);

    var falseErrors = result.ValidationErrors
                            .Where(error =>
                            {
                                if (entityEntry.State != EntityState.Modified) return false;
                                var member = entityEntry.Member(error.PropertyName);
                                var property = member as DbPropertyEntry;
                                if (property != null) return !property.IsModified;
                                return false;
                            });

    foreach (var error in falseErrors.ToArray())
    {
        result.ValidationErrors.Remove(error);
    }

    return result;
}

To the Shimmy sample I’ve added the condition “if (entityEntry.State != EntityState.Modified) return false;” to avoid bypass the validation when adding an entity.

Now if you test the same code as before, you will receive an entity framework exception and no round-trip will be made on sql server:

using (var db = new NorthwindDbContext())
{
    var customer = new Customer
    {
        CustomerId = "ALFKI"
    };
    db.Customers.Attach(customer);

    customer.PostalCode = "123456789000";

    // Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
    // The field PostalCode must be a string or array type with a maximum length of '10'.
    await db.SaveChangesAsync();
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s