Reputation: 1200
I am using Entity Framework Core with a code-first approach. I hit this error when saving the changes to an entity which has a change to one of its related objects:
"The property 'BirdId' on entity type 'Bird' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key first delete the dependent and invoke 'SaveChanges' then associate the dependent with the new principal."
I hit the error when I save the changes to an entity of type Observation
with a updated to the related Bird
object. I have included the models setup below:
public class Observation
{
[Key]
public int ObservationId { get; set; }
// other properties...
public int BirdId { get; set; }
public Bird Bird { get; set; }
}
The Bird class looks like this:
public class Bird
{
[Key]
public int BirdId { get; set; }
// other properties...
public ICollection<Observation> Observations { get; set; }
}
I have relied solely on the EF Core model conventions (I've not added code in the OnModelCreating
method) which, from the EF migration, sets up the database like so:
migrationBuilder.CreateTable(
name: "Observation",
columns: table => new
{
ObservationId = table.Column<int>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
BirdId = table.Column<int>(nullable: false),
},
constraints: table =>
{
table.PrimaryKey("PK_Observation", x => x.ObservationId);
table.ForeignKey(
name: "FK_Observation_Bird_BirdId",
column: x => x.BirdId,
principalTable: "Bird",
principalColumn: "BirdId",
onDelete: ReferentialAction.Cascade);
});
Have I setup the model correctly?
My code for saving the updated Observation looks like this:
observation.BirdId = model.Bird.BirdId;
var bird = await _birdRepository.GetBirdAsync(model.Bird.BirdId);
observation.Bird = bird;
observation.LastUpdateDate = _systemClock.GetNow;
await _unitOfWork.CompleteAsync();
However, I think the problem lies in the way the relationship is setup in the models. Can anyone shed any light on the problem?
Upvotes: 3
Views: 8938
Reputation: 386
observation.Bird
is linked to observation.BirdId
by convention. You're not supposed to change both and it is generally recommended to only change the navigation property.
I'm going to assume that model
is a view model and so you can't use its Bird directly, but basically you can leave out the first line of code and simply set observation.Bird
.
EF gets confused in this case because you are trying to change the relation twice.
Upvotes: 6