diff --git a/docs/src/Entity-Mapping.md b/docs/src/Entity-Mapping.md index f99be9e09..84a1e11e1 100644 --- a/docs/src/Entity-Mapping.md +++ b/docs/src/Entity-Mapping.md @@ -2,9 +2,9 @@ Mapping to entities - an object with a member decorated with a [`KeyAttribute`]( ### Entity Keys -Members decorated with a `KeyAttribute` are not mapped, unless the mapping is a deep clone. Entity key values are usually generated by a data store, and some ORMs will throw an exception if a key value is updated in code. +By default, members decorated with a `KeyAttribute` are not mapped, unless the mapping is a deep clone. Entity key values are usually generated by a data store, and some ORMs will ignore key value updates, or in some cases, throw an exception. -If you need to map to a `KeyAttribute` member, you can override this behaviour by configuring a [custom data source](/configuration/Member-Values). +If you need to map `KeyAttribute` members, you can [configure the behaviour](/configuration/Entity-Mapping) that suits your needs, or configure a [custom data source](/configuration/Member-Values). ### Optional Related Entity Keys diff --git a/docs/src/configuration/Entity-Mapping.md b/docs/src/configuration/Entity-Mapping.md new file mode 100644 index 000000000..d22dcb63f --- /dev/null +++ b/docs/src/configuration/Entity-Mapping.md @@ -0,0 +1,102 @@ +By default, members decorated with a `KeyAttribute` are not mapped, unless the mapping is a deep clone. Entity key values are usually generated by a data store, and some ORMs will ignore key value updates, or in some cases, throw an exception. + +```cs +// Retrieve the existing Customer entity: +var customer = await dbContext + .Customers + .FirstOrDefaultAsync(c => c.Id == customerDto.Id); + +if (customer == null) +{ + // Deal with Customer not found +} + +// Update the Customer from the DTO - this does not map Customer.Id: +Mapper.Map(customerDto).Over(customer); + +// Save the changes - no problems! +await dbContext.SaveChangesAsync(); +``` + +There are circumstances where you might want to map entity keys, though. A typical case might be to [delete an entity by id](https://stackoverflow.com/questions/2471433/how-to-delete-an-object-by-id-with-entity-framework): + +```cs +// Create a dummy Customer entity from the DTO: +var customerToDelete = Mapper.Map(customerDto).ToANew(); + +// Attach then remove the Customer from the context: +dbContext.Customers.Attach(customer); +dbContext.Customers.Remove(customer); + +// Save the changes - no Customer.Id, so does not work! +await dbContext.SaveChangesAsync(); +``` + +### Mapping Keys + +There's a number of options to change entity key mapping behaviour, depending on your needs. + +To map keys by default **in all mappings**, use: + +```cs +Mapper.WhenMapping.MapEntityKeys(); + +// - - - - - - - - - - - - - - - + +// Customer.Id will now be mapped: +var customerToDelete = Mapper.Map(customerDto).ToANew(); +``` + +To map keys by default when mapping **between two particular types**, use: + +```cs +Mapper.WhenMapping + .From() // Apply to CustomerDto mappings + .ToANew() // Apply to Customer creations + .MapEntityKeys(); // Map entity keys + +// - - - - - - - - - - - - - - - + +// Customer.Id will now be mapped: +var customerToDelete = Mapper.Map(customerDto).ToANew(); +``` + +To map keys for an **individual mapping**, use: + +```cs +// Map the DTO, including to Customer.Id: +var customerToDelete = Mapper + .Map(customerDto) + .ToANew(cfg => cfg.MapEntityKeys()); +``` + +## Opting Out + +If the default behaviour is changed to map keys, key mapping can be disabled when necessary. + +To ignore keys when mapping **between two particular types**, use: + +```cs +// Map keys by default: +Mapper.WhenMapping.MapEntityKeys(); + +// Ignore entity keys when mapping from any +// source Type to a Customer: +Mapper.WhenMapping + .To() // Apply to Customer mappings + .IgnoreEntityKeys(); // Do not map entity keys +``` + +To ignore keys for an **individual mapping**, use: + +```cs +// Map keys by default: +Mapper.WhenMapping.MapEntityKeys(); + +// - - - - - - - - - - - - - - - + +// Ignore entity keys for this mapping: +Mapper + .Map(customerDto) + .Over(customer, cfg => cfg.IgnoreEntityKeys()); +``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index aa3ad4542..e79bbae51 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -45,6 +45,7 @@ nav: - Dependency injection: configuration/Dependency-Injection.md - Member values: configuration/Member-Values.md - Constructor arguments: configuration/Constructor-Arguments.md + - Entity mapping: configuration/Entity-Mapping.md - Member name patterns: configuration/Member-Name-Patterns.md - To-string formatting: configuration/To-String-Formatting.md - Enum pairing: Enum-Mapping/#configuring-enum-pairs