Suppose you want a system that lets you plug custom validation rules on your Entity Framework context. The rules would control whether an entity can be saved, updated or deleted, and would be implemented in plain .NET. Yes, I know I already talked about plugable validation in Entity Framework Code First, but this is a different approach.
An example API is in order, first, a ruleset, which will hold the collection of rules:
Next, a rule:
Let’s analyze what we have, starting with the ruleset:
- Only has methods for adding a rule, specific to an entity type, and to list all rules of this entity type;
- By implementing IDisposable, we allow it to be cancelled, by disposing of it when we no longer want its rules to be applied.
A rule, on the other hand:
Has discrete methods for checking if a given entity can be saved, updated or deleted, which receive as parameters the entity itself and a pointer to the DbContext to which the ruleset was applied;
Has a name property for helping us identifying what failed.
A ruleset really doesn’t need a public implementation, all we need is its interface. The private (internal) implementation might look like this:
Basically, this implementation:
Has a collection - a set, actually, which does not allow duplication - of rules indexed by the real Type of an entity (because of proxying, an entity may be of a type that inherits from the class that we declared);
Has generic methods for adding and enumerating rules of a given type;
Has a Dispose method for cancelling the enforcement of the rules.
A (really dumb) rule applied to Product might look like this:
The DbContext is there because we may need to check something else in the database before deciding whether to allow an operation or not.
And here’s how to apply this mechanism to any DbContext, without requiring the usage of a subclass, by means of an extension method:
So, let’s put it all together:
Feel free to use it and extend it any way you like, and do give me your feedback!
As a final note, this can be easily changed to support plain old Entity Framework (not Code First, that is), if that is what you are using.