Skip to content

Commit

Permalink
Documenting entity key mapping configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveWilkes committed Nov 28, 2018
1 parent 8dcbc82 commit 2e29098
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 2 deletions.
4 changes: 2 additions & 2 deletions docs/src/Entity-Mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
102 changes: 102 additions & 0 deletions docs/src/configuration/Entity-Mapping.md
Original file line number Diff line number Diff line change
@@ -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<Customer>();

// 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<Customer>();
```

To map keys by default when mapping **between two particular types**, use:

```cs
Mapper.WhenMapping
.From<CustomerDto>() // Apply to CustomerDto mappings
.ToANew<Customer>() // Apply to Customer creations
.MapEntityKeys(); // Map entity keys
// - - - - - - - - - - - - - - -
// Customer.Id will now be mapped:
var customerToDelete = Mapper.Map(customerDto).ToANew<Customer>();
```

To map keys for an **individual mapping**, use:

```cs
// Map the DTO, including to Customer.Id:
var customerToDelete = Mapper
.Map(customerDto)
.ToANew<Customer>(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<Customer>() // 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());
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 2e29098

Please sign in to comment.