'C# EFCore.BulkExtensions The MERGE statement conflicted with the FOREIGN KEY constraint
Parent:
public class Currency
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string? Name { get; set; }
}
Child:
public class CurrencyRate
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column(TypeName = "date")]
public DateTime Date { get; set; }
[Column(TypeName = "decimal(18,6)")]
public decimal Value { get; set; }
public virtual Currency? Currency { get; set; }
}
Seed:
modelBuilder.Entity<Currency>().HasData(
new Currency { Id = 1, Name = "JPY" },
new Currency { Id = 2, Name = "USD" },
new Currency { Id = 3, Name = "EUR" },
new Currency { Id = 4, Name = "TRY" }
);
Insert:
public async Task UpdateCurrencyRates()
{
var trackedCurrencies = await _context.Currency.ToListAsync();
BulkConfig bulkConfig = new BulkConfig()
{
IncludeGraph = true,
SetOutputIdentity = true,
CalculateStats = true,
PropertiesToIncludeOnUpdate = new List<string> { string.Empty }
};
List<CurrencyRate> currencyRates = GetCurrencyRatesFromSomewhere();
currencyRates.ForEach(currencyRate =>
{
var trackedCurrency = trackedCurrencies.SingleOrDefault(r => r.Name == currencyRate.Currency?.Name);
if (trackedCurrency != null)
{
currencyRate.Currency = trackedCurrency;
}
else if (currencyRate.Currency != null)
{
trackedCurrencies.Add(currencyRate.Currency);
}
});
_context.BulkInsertOrUpdate(currencyRates, bulkConfig);
}
The above code works well unless new currency comes in (the one not included in Seed). Then I get 'The MERGE statement conflicted with the FOREIGN KEY constraint'. Why is it so? From what I read BulkExtensions should insert new currency first, then update CurrencyRates with its Id and only then perform insert of CurrencyRates.
Update: If I do this, it works, but that defeats the grace of the BulkInsert:
currencyRates.ForEach(async currencyRate =>
{
var trackedCurrency = trackedCurrencies.SingleOrDefault(r => r.Name == currencyRate.Currency?.Name);
if (trackedCurrency != null)
{
currencyRate.Currency = trackedCurrency;
}
else if (currencyRate.Currency != null)
{
trackedCurrencies.Add(currencyRate.Currency);
//this line added
await _context.AddAsync(currencyRate.Currency);
}
});
//this line added
await _context.SaveChangesAsync();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|