Winthorpe
Winthorpe

Reputation: 1200

Updating related entity in EF Core

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

Answers (1)

Gamingdevil
Gamingdevil

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

Related Questions