dotnet / dotnet/efcore

Option to store temporary keys in the object fields, to support relations without navigation properties

Open
#34,200 0 comments 0 reactions 0 assignees View on GitHub
area-change-tracking customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

### What problem are you trying to solve?
When adding items to the context, keys are no longer populated. EF does keep a temporary key, but it is only available in the state of the context.
To be able to reference the entities without navigation properties, one must retrieve the internal temporary key from the context.
This requires the code to be tightly coupled with EF, and adds complexity in the code where it is not needed.

The example below creates a `contract` which has a list of `clientContractUsageData`. Code further down the line needs to create entities referencing both the contract and the entries from the list without a navigation property. In order for the code to function, one must retrieve all ids from the context.
```
var contract = new ClientContract
{
...
ClientContractUsageData = new List<..> { ... } // This list of entries is mapped to a separate table
};

// Setting the Temporary keys allows us to define foreign key relations while not yet in the db
contract.Id = _dbContext.Entry(contract).Property(c => c.Id).CurrentValue;

foreach (var usageData in contract.ClientContractUsageData)
{
usageData.Id = _dbContext.Entry(usage).Property(ud => ud.Id).CurrentValue;
}

// Now we can execute code that does not have navigation properties, and requires the id value to set up relations
// This could be code called directly, but this could also be messages stored in the database (outbox pattern) for later execution
await _warrantyInvoiceService.CreateForNewContract(contract.Id, command.Formula);

foreach (var usageData in contract.ClientContractUsageData)
{
await _billingPeriodService.CreateBillingPeriodForUsageData(usageData.Id, command.Formula);
}
```
Having to populate all the temporary keys yourself adds noise to the code, which should be avoidable.

### Describe the solution you'd like
Provide an option to populate the temporary values in the fields of the objects added to the context.

Either as a global option, or a function call on the context
```
//a)
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.PopulateFieldsWithTemporaryKeys();
base.OnConfiguring(optionsBuilder);
}

//b)
_dbContext.FillTemporaryKeys(contract); // This would set the id field, and the id fields of the ClientContractUsageData in the example above.
```

**Why do I think this feature request could be valuable**
The population of the temporary keys allows your code to be completely indifferent to whether it was a real or temp id. Once an object is added to the context, it should be possible to easily reference it using foreign keys and without a navigation property.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.