Reputation: 869
I have two entities that each refer to each other: A Page
entity which has reference to defaultUrl
and a Url
entity which has a reference to a page
.
This is cyclical and so once I add a page and a url what reference each other, I cannot delete them.
I can see two ways to fix it but am not sure of the "Doctrine" way to do it.
I couldn't figure out how to do either of these... do you know??
Thanks!
Upvotes: 2
Views: 484
Reputation: 1061
Here's the Doctrine way of setting this up. As was mentioned before, you need to set at least one of the foreign keys to be nullable.
Also consider setting the onDelete cascades to SET NULL. That will make the process of deleting even simpler -- you won't have to update the key to NULL before deleting the record.
Your schema.yml could look like this:
Url:
columns:
page_id: { type: integer, notnull: true }
relations:
Page: { local: page_id, foreign: id }
Page:
columns:
default_url_id: { type: integer, notnull: false } # ALLOWS NULL foreign key here
relations:
DefaultUrl: { class: Url, local: default_url_id, foreign: id, onDelete: SET NULL }
Upvotes: 3
Reputation: 43280
Rule of thumb, when making foreign keys, always make one either nullable or omit one foreign key definition.
This allows cycle breaking.
Simplest case (SQL Syntax but the sampe principle applies):
CREATE TABLE Employee (
EmployeeId INTEGER NOT NULL IDENTITY(1,1)
ManagerId INTEGER NOT NULL
--...
PRIMARY KEY EmployeeId NONCLUSTERED
FOREIGN KEY FK_Manager REFRENCES Employee(EmployeeId)
)
Can be loop broken as follows:
CREATE TABLE Employee (
EmployeeId INTEGER NOT NULL IDENTITY(1,1)
ManagerId INTEGER NOT NULL
--...
PRIMARY KEY EmployeeId NONCLUSTERED
)
or as follows:
CREATE TABLE Employee (
EmployeeId INTEGER NOT NULL IDENTITY(1,1)
ManagerId INTEGER NULL
--...
PRIMARY KEY EmployeeId NONCLUSTERED
FOREIGN KEY FK_Manager REFRENCES Employee(EmployeeId)
)
I prefer to, when declaring foreign keys, to always trace the diagram and ensure there are no cycles. I will omit the least dangerous keys until all cycles are broken. This ensures that all tables can be bulk exported followed by bulk imported into another database.
EDIT: I find that when you ask a book expert this question you get an answer like turn off the foreign key during delete. This is wrong for two reasons. First, normal transactional operations should not be altering the schema definitions. Second, the rest of the code expects the foreign key to be there and so does not handle it in application code; however schema modifications have a nasty habit of bleeding across transactions or locking entire tables.
Upvotes: 1