Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Core ForeignKeyAttribute on both sides

I have an application with Entity Framework Core with different entities in my context, but there are two of them that require a one-to-zero-or-one relation. My way of doing that and ensuring validation was to do something like the following:

public class PurchasedPackage
{
    public int Id { get; set; }

    ...

    [ForeignKey(nameof(PurchasedPackageModifier))]
    public int? PurchasedPackageModifierId { get; set; }

    public virtual PurchasedPackageModifier PurchasedPackageModifier { get; set; }
}

And

public class PurchasedPackageModifier
{
    public int Id { get; set; }

    ...

    [Required]
    [ForeignKey(nameof(PurchasedPackage))]
    public int PurchasedPackageId { get; set; }

    public virtual PurchasedPackage PurchasedPackage { get; set; }

    ...
}

Where PurchasedPackage is required and PurchasedPackageModifier is optional. By specifying ForeignKey attribute on both sides I'm trying to ensure data integrity across saves to both tables so nobody creates a PurchasedPackage with a non-existent PurchasedPackageModifier and vice versa.

While this works as required I'm getting warnings in my logs stating the following:

'PurchasedPackage.PurchasedPackageModifier' and 'PurchasedPackageModifier.PurchasedPackage' were separated into two relationships as ForeignKeyAttribute was specified on properties 'PurchasedPackageModifierId' and 'PurchasedPackageId' on both sides.

And

'PurchasedPackageModifier.PurchasedPackage' and 'PurchasedPackage.PurchasedPackageModifier' were separated into two relationships as ForeignKeyAttribute was specified on properties 'PurchasedPackageId' and 'PurchasedPackageModifierId' on both sides.

My question is: am I doing this right and should I ignore these warnings in this particular case or there is a better way of achieving same validation/integrity behavior?

like image 350
HardLuck Avatar asked Oct 20 '25 14:10

HardLuck


1 Answers

You’re doing it the right way. According to Microsoft, the reason a warning is shown is because most of the time it's a mistake to put foreign keys on two tables that reference each other, unless of course you're creating a one-to-one relationship. Here's a quote from an Engineering Manager for Entity Framework at Microsoft:

The warning is basically saying that using ForeignKeyAttribute in this way creates two relationships because it is not uncommon for people to do this by mistake not intending it to create two relationships.

https://github.com/dotnet/efcore/issues/11756#issuecomment-383640800

To suppress the warning, make a call to DbContextOptionsBuilder.ConfigureWarnings() in your DbContext class:

using Microsoft.EntityFrameworkCore.Diagnostics;

public sealed class SampleDbContext : DbContext
{
    /* DbContext code... */
    protected override void OnConfiguring(DbContextOptionsBuilder Builder)
    {
        Builder.ConfigureWarnings(delegate (WarningsConfigurationBuilder warnings)
        {
            // The following line will suppress the warning
            // "'Foo.Bar' and 'Bar.Foo' were separated into two relationships as
            // ForeignKeyAttribute was specified on properties 'BarId' and
            // 'FooId' on both sides."
            warnings.Ignore(CoreEventId.ForeignKeyAttributesOnBothNavigationsWarning);
        });
    }
    /* DbContext code... */
}
like image 163
user3163495 Avatar answered Oct 22 '25 05:10

user3163495



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!