Unavi
Unavi

Reputation: 148

Entity Framework Core set Navigation property to null with include doesn't work

I am trying to reset the project navigation property in my asset entity.

Asset Model (removed everything unrelated):

public class Asset
{
    public int Id { get; set; }
    public int? ProjectId { get; set; }
    public Project Project { get; set; }
}

Reset logic:

var asset = await context.Assets.Include("Project").FirstAsync(a => a.Id == assetId);
asset.Project = null;
asset.ProjectId = null;
await context.SaveChangesAsync();

I included the project in the query and tried to set the Project and the ProjectId to null, but it doesn't update in the database. Additionally I already tried to only set the Project and only set the ProjectId to null but neither works.

There are a few related questions on SO for this problem, but for all of them the Include("xy") seems to solve the problem.

Upvotes: 1

Views: 5308

Answers (1)

Unavi
Unavi

Reputation: 148

Easy to solve but hard to track down. I called context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; on the context at some point before, which makes the result read only. source

Two solutions:

  • Either remove this line (for me it was a leftover from playing around),
  • or add .AsTracking() to the query if you want to keep the general no tracking behavior.

With my example from above it would look like:

var asset = await context.Assets.Where(a => a.Id == assetId).Include("Project")
                                .AsTracking().FirstOrDefaultAsync()
asset.Project = null;

If you have the foreign key available on your model you can remove the include and just set the foreign key to null like this:

var asset = await context.Assets.Where(a => a.Id == assetId).AsTracking().FirstOrDefaultAsync()
asset.ProjectId = null;

And again without context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; you can omit .AsTracking() because that is the standard behavior.

Upvotes: 1

Related Questions