I have a .NET Core 3.1 library, which uses a database-first Entity Framework Core class.
To generate this class I use this package manager command:
Scaffold-DbContext “<my connection string>” Microsoft.EntityFrameworkCore.SqlServer
-OutputDir Database/GeneratedNew
-Context DatabaseContextBase -DataAnnotations
This worked for a long while, but now I am updating with more complexity and for a first time I am adding foreign keys.
In the database I have a table with primary key column ServerId. And another table (Currency) with the FK key column OriginServer.
They are both defined as numeric(20, 0).
This is the FK script, in case I messed it up:
ALTER TABLE [dbo].[Currencies] WITH NOCHECK
ADD CONSTRAINT [FK_Currencies_MainServerData]
FOREIGN KEY([OriginServer]) REFERENCES [dbo].[MainServerData] ([ServerId])
ON UPDATE CASCADE
This is the code that is generated (I've omitted a lot of unrelated fields):
public partial class MainServerData
{
public MainServerData()
{
Currencies = new HashSet<Currency>();
}
[Key]
[Column(TypeName = "numeric(20, 0)")]
public decimal ServerId { get; set; }
[InverseProperty(nameof(Currency.OriginServerNavigation))]
public virtual ICollection<Currency> Currencies { get; set; }
}
[Index(nameof(OriginServer), Name = "IX_OriginServer_Currencies")]
[Index(nameof(SpecialKey), Name = "IX_SpecialKey_Currencies")]
public partial class Currency
{
public Currency()
{
Wallets = new HashSet<Wallet>();
}
[Key]
public int Id { get; set; }
[Column(TypeName = "numeric(20, 0)")]
public decimal OriginServer { get; set; }
[Required]
[StringLength(64)]
public string SpecialKey { get; set; }
[Required]
[StringLength(16)]
public string Symbol { get; set; }
[ForeignKey(nameof(OriginServer))]
[InverseProperty(nameof(MainServerData.Currencies))]
public virtual MainServerData OriginServerNavigation { get; set; }
[InverseProperty(nameof(Wallet.Currency))]
public virtual ICollection<Wallet> Wallets { get; set; }
}
And part of the DbContext code:
modelBuilder.Entity<Currency>(entity =>
{
entity.HasOne(d => d.OriginServerNavigation)
.WithMany(p => p.Currencies)
.HasForeignKey(d => d.OriginServer)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Currencies_MainServerData");
});
Until I had to use the FK, it was all working good. But now when I try to access:
database.MainServerData
.FirstOrDefault(s => s.ServerId == decimalId)?.Currencies?.FirstOrDefault()
This is always null, even when there are entries in the database.
I can't figure out what the problem is.
EDIT: To continue work, while investigating the issue, I decided to create a helper method, that returns the Currency as intended:
public partial class MainServerData
{
public Currency GetCurrency(DatabaseContextBase database)
{
return database.Currencies.FirstOrDefault(c => c.OriginServer == this.ServerId);
}
}
In addition, Currencies also have Wallets FK, which also does not work:
modelBuilder.Entity<Wallet>(entity =>
{
entity.HasOne(d => d.Currency)
.WithMany(p => p.Wallets)
.HasForeignKey(d => d.CurrencyId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Wallets_Currencies");
});
This is in the Currency class:
[InverseProperty(nameof(Wallet.Currency))]
public virtual ICollection<Wallet> Wallets { get; set; }
Yet this returns 0 (pickedCurrency is correct and it has wallets in the DB)
var walletCount = pickedCurrency.Wallets.Count();
I assume this could be an issue with EntityFramework Core, but I have not managed to confirm this suspicion. Perhaps my version is outdated, it's v5.0.7? I will try to update it. (edit: updated to v5.0.17, did not fix the problem)