Reputation: 7198
Is there any way to update entity relation before calling SaveChanges in generic way?
public class Vehicle
{
public int Id { get; set; }
public int OwnerId { get; set; }
[ForeignKey("OwnerId")]
public Person Owner { get; set; }
}
For example I would like to create new Person, and assign it to Vehicle before Id is generated (before calling SaveChanges). I know I can do it like:
entry.Property("OwnerId").CurrentValue = newId;
But the problem is that I don't know the Id of the new entity before calling SaveChanges
.
What I'm trying to achieve is to automatically create a copy of the Owner when it changes, and assign the Owner to the copy. For sure I have to do it somehow inside SaveChanges override.
Something like:
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
foreach (var entry in ChangeTracker.Entries())
{
foreach (var reference in entry.References)
{
if (reference.TargetEntry != null && reference.TargetEntry.State == EntryState.Modified)
{
// make a copy of target entry and update reference to it,
// note: you can't really add new entries inside this loop as it will throw an exception, so all the adding has to be done outside
// I would like to set this newEntity as the Owner
var newEntity = (BaseEntity)entry.CurrentValues.ToObject();
newEntity.Id = 0;
}
}
}
return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
How I want it to work:
//would insert new Person row and update OwnerId to point to this new row
vehicle.Owner.Name = "NewName";
Upvotes: 0
Views: 1453
Reputation: 32058
You should update the reference so that the Id is updated when you don't have the Id:
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
foreach (var entry in ChangeTracker.Entries())
{
bool shouldUpdateReference = false;
foreach (var reference in entry.References)
{
if (reference.TargetEntry != null && reference.TargetEntry.State == EntryState.Modified)
{
shouldUpdateReference = true;
}
}
// I imagine this has to be done outside the foreach
// since you are modifying a reference and that should
// update the References collection
if (shouldUpdateReference)
{
entity.Reference("Owner").CurrentValue = newOwner;
}
}
return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
Upvotes: 2