Fix loan edit concurrency error with ExecuteDeleteAsync
The change tracker-based approaches (RemoveRange, Clear) both caused DbUpdateConcurrencyException when deleting amortization entries. Use ExecuteDeleteAsync to delete directly in the database, bypassing the change tracker entirely. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -64,13 +64,14 @@ public class LoanService : ILoanService
|
|||||||
|
|
||||||
public async Task<LoanDetailResponse> UpdateLoanDetailAsync(Guid userId, Guid accountId, CreateLoanDetailRequest request)
|
public async Task<LoanDetailResponse> UpdateLoanDetailAsync(Guid userId, Guid accountId, CreateLoanDetailRequest request)
|
||||||
{
|
{
|
||||||
var account = await _db.Accounts.Include(a => a.LoanDetail).ThenInclude(l => l!.AmortizationEntries)
|
var account = await _db.Accounts.Include(a => a.LoanDetail)
|
||||||
.FirstOrDefaultAsync(a => a.Id == accountId && a.UserId == userId)
|
.FirstOrDefaultAsync(a => a.Id == accountId && a.UserId == userId)
|
||||||
?? throw new KeyNotFoundException("Account not found");
|
?? throw new KeyNotFoundException("Account not found");
|
||||||
|
|
||||||
var l = account.LoanDetail ?? throw new KeyNotFoundException("No loan detail found");
|
var l = account.LoanDetail ?? throw new KeyNotFoundException("No loan detail found");
|
||||||
|
|
||||||
l.AmortizationEntries.Clear();
|
// Delete old entries directly in DB, bypassing change tracker
|
||||||
|
await _db.AmortizationEntries.Where(e => e.LoanDetailId == l.Id).ExecuteDeleteAsync();
|
||||||
|
|
||||||
l.OriginalBalance = request.OriginalBalance;
|
l.OriginalBalance = request.OriginalBalance;
|
||||||
l.InterestRate = request.InterestRate;
|
l.InterestRate = request.InterestRate;
|
||||||
@@ -83,7 +84,10 @@ public class LoanService : ILoanService
|
|||||||
|
|
||||||
var entries = GenerateAmortizationSchedule(l);
|
var entries = GenerateAmortizationSchedule(l);
|
||||||
foreach (var entry in entries)
|
foreach (var entry in entries)
|
||||||
l.AmortizationEntries.Add(entry);
|
{
|
||||||
|
entry.LoanDetailId = l.Id;
|
||||||
|
_db.AmortizationEntries.Add(entry);
|
||||||
|
}
|
||||||
await _db.SaveChangesAsync();
|
await _db.SaveChangesAsync();
|
||||||
|
|
||||||
var schedule = entries.Select(e => new AmortizationEntryResponse(e.PaymentNumber, e.PaymentDate, e.PaymentAmount, e.PrincipalAmount, e.InterestAmount, e.EscrowAmount, e.RemainingBalance)).ToList();
|
var schedule = entries.Select(e => new AmortizationEntryResponse(e.PaymentNumber, e.PaymentDate, e.PaymentAmount, e.PrincipalAmount, e.InterestAmount, e.EscrowAmount, e.RemainingBalance)).ToList();
|
||||||
|
|||||||
Reference in New Issue
Block a user