Reputation: 1492
I am using Entity Framework Core 2.2 to manage a SQL Server database of traded currencies. There are two entities in the model. The first is Currency
, which specifies a trade-able currency, and the other is CurrencyPair
, which specifies a pair of currencies that can be exchanged for one another.
public class Currency
{
public ulong Id { get; set; }
public string Name {get; set; }
[NotMapped]
public IEnumerable<CurrencyPair> Pairs
{
get { PairsAsBase?.Concat( PairsAsQuote ?? new CurrencyPair[0] ); }
}
public virtual IEnumerable<CurrencyPair> PairsAsBase { get; set; }
public virtual IEnumerable<CurrencyPair> PairsAsQuote { get; set; }
}
public class CurrencyPair
{
public ulong Id { get; set; }
public string Name { get; set; }
public ulong BaseCurrencyId { get; set; }
public ulong QuoteCurrencyId { get; set; }
public virtual Currency BaseCurrency { get; set; }
public virtual Currency QuoteCurrency { get; set; }
}
I would like to constrain the CurrencyPair
table to disallow rows from having the same Currency
for both BaseCurrency
and QuoteCurrency
fields. That is, if a specific currency has Id = 1
, then a currency pair specifying BaseCurrencyId = 1
and QuoteCurrencyId = 1
would not be allowed.
Here is my DbContext.OnModelCreating
implementation:
protected override void OnModelCreating( ModelBuilder modelBuilder )
{
modelBuilder.Entity<Currency>().HasKey(x => x.Id);
modelBuilder.Entity<Currency>().HasAlternateKey(x => x.Name);
modelBuilder.Entity<Currency>()
.HasMany(x => x.PairsAsBase)
.WithOne(x => x.BaseCurrency)
.HasForeignKey(x => x.BaseCurrencyId);
modelBuilder.Entity<Currency>()
.HasMany(x => x.PairsAsQuote)
.WithOne(x => x.QuoteCurrency)
.HasForeignKey(x => x.QuoteCurrencyId);
modelBuilder.Entity<CurrencyPair>().HasKey(x => x.Id);
modelBuilder.Entity<CurrencyPair>()
.HasOne(x => x.BaseCurrency)
.WithMany(x => x.PairsAsBase)
.HasForeignKey(x => x.BaseCurrencyId);
modelBuilder.Entity<CurrencyPair>()
.HasOne(x => x.QuoteCurrency)
.WithMany(x => x.PairsAsQuote)
.HasForeignKey(x => x.QuoteCurrencyId);
}
TL;DR: How can I ensure that two foreign key columns in a table do not both reference the same entity (using Entity Framework Core 2.2)?
Upvotes: 0
Views: 694
Reputation: 28434
AFAIK there is no good way to enforce your rule at the model builder lvl. The next best thing would be to intercept SQL commands that could generate faulty data through an ef context, but the API isnt mature enough to make this an easy option.
In my opinion, the only options that you have left have no relation whatsoever to EF:
CHECK
constraintUpvotes: 1
Reputation: 617
Did you try Global query filters, this should help you protect some unwanted to be show up when you query
modelBuilder.Entity<CurrencyPair>().HasQueryFilter(p => p.BaseCurrency != p.QuoteCurrency);
Data will still store in your table but it not show up when you using it.
Upvotes: 1