0-1 self referencing relationship in EF Core

c# entity-framework entity-framework-core

Question

Idea: I have a Key entity, which can be replaced (rotated) by other Key with a delay. I was thinking of implementing it as:

class Key {
    string Id;
    string ReplacesId;
    Key Replaces;
    string ReplacedById;
    Key ReplacedBy;
    DateTime Expires;
    // ...
}

So when I want to replace it, I'd create another key and then reference new and old keys to each other. And if anyone of them is deleted, the other one would be as well.

And that's how I implemented, with this Fluent mapping:

modelBuilder.Entity<Key>().HasOne(x => x.ReplacedBy)
            .WithOne(x => x.Replaces)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.Cascade);

Replacement logic:

oldKey.ReplacedBy = newKey;
oldKey.ReplacedById = newKey.Id;
newKey.Replaces = oldKey;
newKey.ReplacesId = oldKey.Id;

_dbContext.Keys.Update(newKey);
_dbContext.Keys.Update(oldKey);

await _dbContext.SaveChangesAsync();

But it seems that ReplacedById ReplacesId or one of them are used like regular fields ant not FK, because when I try to delete one of them, they don't cascade.

Could I make this work, or should I just introduce Rotations/Replacements table?

1
4
2/15/2019 12:38:51 AM

Accepted Answer

But it seems that ReplacedById ReplacesId or one of them are used like regular fields ant not FK, because when I try to delete one of them, they don't cascade.

This is because your Fluent API configuration is not done in correct way. It actually should be as follows:

modelBuilder.Entity<Key>().HasOne(k => k.Replaces)
                          .WithOne()
                          .HasForeignKey<Key>(k => k.ReplacesId)
                          .IsRequired(false);

modelBuilder.Entity<Key>().HasOne(k => k.ReplacedBy)
                          .WithOne()
                          .HasForeignKey<Key>(k => k.ReplacedById)
                          .IsRequired(false);

Now everything will generate and work as expected!

Note: It will generate onDelete: ReferentialAction.Restrict because you cannot cascade between them because it will cause multiple cascade paths.

2
2/15/2019 12:44:08 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow