Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
There are four main parts of the
NOTE: By validation I mean using the
Validator.TryValidateObject method on every entity being written
to the database.
By default GenericServices does NOT validate data written to the database - it assumes that the front-end
has validated the data. But it can be useful to turn on validation, especially if you are using the
SaveChangesExceptionHandler fuction - (see below).
You have two ways to turn on validation when GenericServices calls
SaveChanges - globally via the
GenericServicesConfig class at startup (see below), or individually using the
If set to true then any Create/Update/Delete that is given an entity classes will validate that entity class on save. It will also call the
SaveChangesExceptionHandler (see below) if an exception occurs. This is the ONLY way to turn on validation for direct-access writes
If set to true then any Create/Update/Delete calls with DTOs will include a validation of the data on save. It will also call the
SaveChangesExceptionHandler (see below) if an exception occurs. You can use
PerDtoConfig<TDto, TEntity to only set validation for a single DTO/entity. The
PerDtoConfig setting takes precedence, and can force validation on or off.
2. Injecting before SaveChanges
If you assign a method to the
BeforeSaveChanges property in
GenericServicesConfig, then it will be called just before SaveChanges/Async is called. The method takes in the current DbContext, which allows you access to the
ChangeTracker method to find out the state of all the tracked entities. The method returns an
IStatusGeneric result and if that status result has errors, i.e.
status.IsValid == false, then it will not call SaveChanges/Async.
How you use this is up to you, but here are some suggestions:
- Add your own validation approach - someone wanted this to apply fluentvalidation.
- Maybe add some code to update certain entities.
- Logging. etc.
3. SQL Error handling
If you set this property to a method it will be called if there is an exception when SaveChanges/Async is called. You method should either:
- Return a IStatusGeneric if it handled the exception (either by returning a error message or a status message) if it successfully handled the exception.
- Returns null if it didn't recognise the exception/error and couldn't handle it. In that case the code will rethrow the exception and it will bubble up to the top.
4. ReadSingle and nulls
Whether returning a null from a
ReadSingleAsync is an error or not depends on what you are doing. For instance, when working with html/razor you most likely want to tell the user that was an error. But with Web API it's not an error - you just return
NotFound (HTTP 404).
You can control whether the read of null is an error via the
NoErrorOnReadSingleNull property in the config. By default it adds an error, but if set to
true it will not add an error, but it will set the
Message to "The <Class Name> was not found."
5. Name matching
The name matcher is used to match the properties in a DTO with the property names in your DDD-styled entity access methods. The default name matcher matches camel and Pascal-case words by simple string matching. If you want a different matching scheme you can write your own, using the
DefaultNameMatcher as a template.