Let me preface this question and state that using the Entity Framework is not an option for us.
In our financial organization, we have business units that will be used in all decisions. Some have a user interface that is not. Validation and business rules must be contained within the entity.
I encode the DALs and DTOs that are created for me, and these DALs use procs to run CRUD in the database (maybe SQL may be Oracle).
So, when I create MVC, WCF, console applications, etc., the question was glaring if the best validation method were implemented.
Here are some typical properties of an entity object:
[DefaultValue("")] public string Branch { get { return _branch; } set { if (value != null && value == _branch) return; const string propertyName = "Branch"; ValidationInstance.Clear(propertyName); ValidationInstance.ValidateRequired(propertyName, value); ValidationInstance.ValidateNumeric(propertyName, value); ValidationInstance.ValidateLength(propertyName, value, 2); _branch = value; if (EntityState != EntityStateType.New) EntityState = EntityStateType.Changed; } } [DefaultValue(0)] public decimal HighDefermentMargin { get { return _highDefermentMargin; } set { if (value == _highDefermentMargin) return; const string propertyName = "HighDefermentMargin"; ValidationInstance.Clear(propertyName); ValidationInstance.ValidateRange(propertyName, value); _highDefermentMargin = value; if (EntityState != EntityStateType.New) EntityState = EntityStateType.Changed; } }
As you can see, there is a combination of data annotations and explicit calls to the validation class to perform an increasingly detailed validation.
In the MVC application, we carefully duplicate the validation in the ViewModel, so we get the client-side and server-side validation. Here is the version of ViewModel of the same property on top:
[Required] [Range(0.0, 99.99)] [Display(Name = "High Deferment Margin")] public decimal HighDefermentMargin { get; set; }
The main difference here is that the check essentially loads the errors into the error collection in the Validation class, which can be requested at the moment the object is sent for storage. If (! IsValid), then create a custom exception containing an array of errors. The controller moves around them and adds them to the ModelState.
I am starting to work on some classes that have literally a couple of hundred fields. Even if they are broken down into OO, the number of fields is still very large. These are credit certificates, etc., which contain a lot of data for one record. To write validation that many properties make me want to vomit. I can't just write a utility for creating entities and validating, because business rules are what govern the validation, not the database. The field value can be nullified in db, but it is not allowed to remain in it as null based on business rules, or the field can be empty, but only if a separate field has a value, etc.
So, you can only use data annotations in the view model. And does entity essentially achieve the same results? I can write custom validators for custom validation, and then business rules for more complex things. Will verification errors be thrown to a higher level from the object, so that the user interface can inform the user in the same convenient way as ModelState? What are others doing in the same situation?