EF has an strange behaviour in this case: obviously, as it's a new entity, and the Id
will be generated buythe db, it isn't initialized and has its default value of 0.
When EF tries to determine how to save this entity, it finds that its Id
and its ParentId
are equal (both are equal to zero). This makes EF find a circular reference of the entity with itself, and thus the error.
To solve the problem you simply have to break the circular reference. As the value of the Id
will eventually be generated by the database, it doesn't matter which value it has when it's added to the context for saving. So, you simply have to give the Id
a value other than zero, and it works like a charm.
In this partiuclar case, I'm handling legacy code, and this is the only solution. But, for a new application, see the recommendations below.
Avoiding this problem by design
The simplest solution for this problem, it's to avoid having an entity with Id = 0. In this way, there will be no accidental "circular reference".
If you see hvd's comments, you'll find that there is a second problem: you can't insert the first row using your EF code, because the Id
and the ParentId
would have to be the same, and, as stated, this will make EF fail. To solve this problem you have two options:
- Change the design so that
ParentId
can be null (make itint?
). In this way, you can insert the first row with a null value inParentId
- Execute a direct
INSERT INTO
sentence for the first insertion (in SSMS, using ADO.NET, executing the query directly from the context...). If you do so, the insertion will be handled directly by the DB, and there will be no problem.
NOTE 1: In both cases, inserting a row related to itself is impossible through EF.
NOTE 2: Depending on the number of rows in the table, making the parent id nullable can degrade query performance, and take up more disk space: an INT NOT NULL
column takes up less space, and gives better performance on indexing than an INT NULL
column. If this is a concern, take the 2nd solution.