I am inserting a record into the database, which looks like this:
class Transaction
{
int Id;
}
What I want, is when I insert this object, I want to create another record, like this:
class TransactionUpdate
{
int StartingTransactionId;
int EndingTransactionId;
}
What I have so far, is a loop in my SaveChanges on the DbContext, which takes new Transaction objects that will be created and creates TransationUpdate objects and attaches these to the DbContext.
public override int SaveChanges()
{
foreach(var entry in this.ChangeTracker.Entries())
{
if(entry.Entity is Transaction)
{
var update = new TransactionUpdate();
update.StartingTransactionId = ((Transaction)entry.Entity).PreviousTransactionId;
update.EndingTransactionId = ((Transaction)entry.Entity).Id; // This is zero because the entity has not been inserted.
this.TransactionUpdates.Add(update);
}
}
}
The problem is, I cannot properly create a TransactionUpdate because I do not have 'EndingTransactionId', or, the Id of the Transaction I am currently inserting.
How can I solve this problem?
Many Thanks.
SOLVED
I have done what Ladislav suggested and am now creating a list of items to add, along with references to the objects that are required to insert them. Thus:
public override int SaveChanges()
{
var transactionUpdatesToAdd = new List<Tuple<TransactionUpdate, Transaction>>();
foreach (var entry in this.ChangeTracker.Entries<Transaction>())
{
if (entry.State == EntityState.Added)
{
var update = new TransactionUpdate();
update.StartingTransactionId = ((Transaction)entry.Entity).PreviousTransactionId;
transactionUpdatesToAdd.Add(new Tuple<TransactionUpdate, Transaction>(update, entry.Entity));
}
}
using(var scope = new TransactionScope())
{
// Save new Transactions
base.SaveChanges();
// Update TransactionUpdates with new IDs
foreach (var updateData in transactionUpdatesToAdd)
{
updateData.Item1.EndingTransactionId = updateData.Item2.Id;
this.TransactionUpdates.Add(updateData.Item1);
}
// Insert the new TransactionUpdate entities.
return base.SaveChanges();
}
Based on your description I guess you are using autogenerated Id in database. You will not receive this Id befere executing SaveChanges
on the context. You have to divide operation into two separate modifications:
public override int SaveChanges()
{
// call base context saving operation to insert all Transactions
base.SaveChanges();
foreach(var entry in this.ChangeTracker.Entries())
{
if(entry.Entity is Transaction)
{
var update = new TransactionUpdate();
update.StartingTransactionId = ((Transaction)entry.Entity).PreviousTransactionId;
update.EndingTransactionId = ((Transaction)entry.Entity).Id;
this.TransactionUpdates.Add(update);
}
}
// save changes again to insert all TransactionUpdates
base.SaveChanges();
}
You should wrap it into TransactionScope
to perform whole saving as atomic operation.