✅ EFCore Nullability and Circular References
I have 2 tables which have FK's to each other due to the relationship.
I'm trying to add some seed data for a profile that needs to be created on initialisation.
I've tried two ways...
1. I'm getting an SQL 19 error which is a expected field that isn't provided (NULL). If I set the FK in EFAlias to Nullable with
?
, then the field in the database isn't populated (which makes sense). However, with the above scenario if I ever lookup the seeded user from their EFAlias, FK to EFUser isn't populated. So it's not possible.
2. If I remove the Nullable statement in the property and provide the UserId and AliasId in the seed data, the migration fails due to Circular Reference (which again, makes sense)
Is there a way I can both have each field populated and required (not nullable)?
Prefixed tables with EF just to make it a little clearer.
SEED: (2nd example - circular reference)
MODEL: (1st example - missing FK in EFAlias)
46 Replies
You can't have a circular ref thing required if you want db constraints.
But you didn't show your lookup code - that's probably the issue
I can't build the migrations or database, I haven't wrote any lookup code yet. 😄
I'm not really sure how to go forward here since I need to know the User from the Alias.
The migration works from example 1 and the database updates as expected, it's just the EFAlias FK for EFEntity isn't populated. 😦
Here's the database entry example for Example 1.
Example 2's migration doesn't build, obviously. 🙂
Sorry, I don't really get your situation. If you're seeding data then just add it
The issue is that I need the EFAlias (screenshotted above) to have the FK to EntityId.
I can't, because it's circular.
You can, just do it
?
I legit can't. 😭
Why?
If I seed
CurrentAliasId in EFEntity
and EntityId in EFAlias
that's circular and EFCore says no. 😄You said you could do it with nullable
But then the field is null.
I have to remove the circular entry though - which is why it's null to be explicit
Does the field already exist?
If it's new, how could the migration add data for it?
No, this is a new database. I'm dropping the database and deleting the migration each time I try this out. It's all fresh data.
Then it can't magically pick the right fk
Yes, the problem being if the field is set explicitly it causes circular reference.
Though, I need it set.
I need to be able to lookup users by Aliases. But also lookup aliases by users.
Fun problem. 😄
I don't see the problem
Then how do I solve it? 😄
Just add the data 🤷♂️
How?
I've explained now that I can't due to circular.
EFCore literally won't create the migration.
The thing that's circular os optional. You can add it any time
You keep saying I can without saying how.
How do I avoid EFCore's migration restriction?
You just assign it and save changes
Manually?
You said starting from scratch. What is this migration
EFCore's migration
dotnet ef migrations add Init --context SqliteDataContext
You also said it's not a problem with optional fks
Updating the field manually via accessing the DB and adding it isn't practical.
D: they're examples to explain my problem.
There not solutions. If they were solutions I wouldn't be here.
1. I can't add circular FK due to Migration failure of Circular Reference.
2. I don't want to null the FK since it needs to be populated.
You don't have a choice. It must be nullable of it's circular
Okay. Let's say I make it null.
I still can't add the data since it's circular!
You can. It's just a reference to another item
One sec. Let me record gif of me showing this
I highlight both circular references
I go to EFAlias and show you the nullable state
I then run the migration - it fails for circular
oh, welp, gif broke half way apparently. I run the migration right after it freezes and the same error as the terminal currently has
I can't see hardly anything on mobile.
eh. You're just going to have to take my word for it.
Even with the fields being nullable, the migration won't build due to being circular.
Did you also remove the cascade delete behaviour?
I'm not too sure what that is sorry
I thought that should have been automatic with an optional fk but maybe not.
There's something like 'OnDelete(...)' available in the model builder. Suggest looking into that
Is that relevant to this problem though or just an observation?
Yes it's relevant if it has been implicitly set up, because that blocks circular dependencies
I suppose another point, if I'm finding it this hard to do circular reference, is this normal or is there some fundamental design issue?
Think you're not familiar with dealing with db constraints?
But yeah, I'm not db expert either but don't think circular refs are too common. But afaik, they're workable with optional fks and no cascade delete
Alright, I'll take a look at that. I'll leave this open to see if anyone else has any ideas. Thanks for your time. 🙂
It's easy to just do it on nosql because it doesn't scream at you if the target is missing
Okay, so I decided to redo this structure. I'm getting told by a few people circular references are not a great way to go about it. 😄
I've created a new table which just has foreign keys to Entity and Alias.
This gets rid of the circular references, just makes a little more awkward to access the data I need. It's a compromise, I guess. 🤷♂️