-
Notifications
You must be signed in to change notification settings - Fork 96
Update
The update of an entity in the database uses CrudServices's UpdateAndSave
method.
In web applications this has a typical two-stage update consisting of
-
ReadSingle<EntityOrDto>(key)
to show the user the current state, some of which will be editable. -
UpdateAndSave(Data)
orUpdateAndSave(JsonPatchDocument)
to update the entity.
NOTE: The UpdateAndSave
method uses EF Core Tracking Snapshots for updates, not the Update
method. This means it produces efficient database updates.
In a DDD-styled class you will have a series of methods to update the data inside the class. There are two types of updates.
The example methods are taken from the Book class in this repo.
These are fairly simple, often taking the data provided to the method and updating the properties.
-
UpdatePublishedOn
method - updates book's PublishedOn property. -
AddPromotion
method- adds/updates a price promotion on a book. This returnsIStatusGeneric
because it contains some error checks. -
RemovePromotion
- removes a price promotion on a book (See note 4).
These are more complex because you often need the relationship loaded before you can update it. You have two options:
-
AddReviewWithInclude
method - adds a new review to the book. -
RemoveReviewWithInclude
method - removes a review from the book.
See IncludeThen Feature page for more information on how to use IncludeThen
attribute on your DTO.
Here you have access to the database via the context
parameter that EfCore.GenericServices will provide. This allows full control over how you access the database (but you mustn't call SaveChanges
!). Here are some examples.
-
AddReview
method - adds a new review to the book. -
RemoveReview
method - removes a review from the book. The RazorAppPage application contains multiple examples of the use of theUpdateAndSave
method:
-
Pages/Authors/Edit - updates an
Author
entity using the AutoMapper Save mapping.
See article Pragmatic Domain-Driven Design: supporting JSON Patch in Entity Framework Core for more on this.
Potential security issue with standard-styled entity classes
For standard-styled entity classes, or any updates done by AutoMapper it is really important to use the
[ReadOnly(true)]
attribute to mark those properties you DON'T want updated in the database (see
this doc).
Otherwise you have a vulnerability, as the values that you showed but didn't expect to change, like the title, could be changed by someone hacking the HTTP request.
NOTE: You do not need [ReadOnly(true)]
when using DDD-styled entity classes.
- If the entity class has any methods that return
void
orIStatusGeneric
then it will look at these to do the update. Otherwise it tries to use AutoMapper. - If there are methods in the entity it will try to match the DTOs name, (minus this set of possible DTO endings: "Dto", "VM", or "ViewModel" ignoring case). If there is a match it will set this as the default method to use.
- You can state exactly what type/name of method/AutoMapper you want to use, by providing a second parameter to the command, e.g.
_service.UpdateAndSave(Data, "UpdatePublishedOn")
. This is useful if there are multiple methods that will match the DTO non-read-only properties (See How GenericServices matches a DTO to a DDD method for more on this).
The options for the second parameter are:- methodName - use a specific named static method, e.g. "AddPromotion"
- methodName(n) - use a specific named static method with n parameters, e.g. "AddPromotion(3)"
- AutoMapper - use AutoMapper's save mapping to copy the DTO into the entity
- For methods with no parameters, e.g.
RemovePromotion()
method inBook
entity, you must define the method name either by:- Creating a DTO name that will select the method (see note 2)
- Providing a second parameter of the call, e.g.
_service.UpdateAndSave(Data, "RemovePromotion")
- or by providing a PerDtoConfig to the DTO with the
UpdateMethod
overriden with the name.