Create one-to-many relationship by using Entity Framework Core database first

Viewed 139

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)

0 Answers
Related