question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Setting a navigation ID property to null deletes the entity with that property

See original GitHub issue

I’m going through the process of trying to upgrade from .NET 3.1 to .NET 6. I’ve managed to get everything building and have upgraded various NuGet packages across my solution.

After trying to run my unit tests, I am encountering some strange problems with some EF operations. I am using the In-memory database provider for these unit tests.

I have a set-up similar to the following:

Entities:

public class EntityA
{
	public Guid Id { get; set; }
	public Guid? EntityBId { get; set; }
	public EntityB EntityB { get; set; }
}

public class EntityB
{
	public Guid Id { get; set; }
	public string Name { get; set; }
}

Configurations:

public class EntityAConfiguration: IEntityTypeConfiguration<EntityA>
{
	public void Configure(EntityTypeBuilder<EntityA> builder)
	{
		builder.ToTable("EntitiyAs");

		builder.Property(e => e.Id)
			.HasColumnName("EntitiyAId")
			.IsRequired();
		
		builder.HasKey(e => e.Id)
			.HasName("PK_EntityAs");

		builder.HasIndex(e => e.EntityBId)
			.HasName("IX_EntityAs_EntityBId");

		builder.HasOne(e => e.EntityB)
			.WithMany()
			.HasForeignKey(e => e.EntityBId)
			.HasConstraintName("FK_EntityA_EntityBs_EntityBId");
	}
}

public class EntityBConfiguration: IEntityTypeConfiguration<EntityB>
{
	public void Configure(EntityTypeBuilder<EntityB> builder)
	{
		builder.ToTable("EntityBs");

		builder.Property(e => e.Id)
			.HasColumnName("EntityBId")
			.IsRequired();

		builder.HasKey(e => e.Id)
			.HasName("PK_EntityBs");
	}
}

Creating my test DBContext like this:

private TestDbContext GenerateDbContext()
{
	var options = new DbContextOptionsBuilder<TestDbContext>()
		.UseInMemoryDatabase(Guid.NewGuid().ToString())
		.EnableSensitiveDataLogging()
		.Options;

	return new TestDbContext(options);
}

In my tests, I am pre-populating a few of these entities in the DbContext before executing the method I want to test. The method under test looks like this:

public async Task RemoveEntityBFromAssociatedEntityA(Guid entityBId)
{
	var entityB = await _dbContext.EntityBs.SingleOrDefaultAsync(g => g.Id == entityBId);
	if (entityB == null)
	{
		// throw exception...
	}

	var entityA = await _dbContext.EntityAs.SingleOrDefaultAsync(s => s.EntityBId == entityB);
	if (entityA == null)
	{
		// throw exception...
	}
	
	entityA.EntityBId = null;
	_dbContext.entityAs.Update(entityA);
	await _dbContext.SaveChangesAsync();
}

What I am doing here is removing the association to EntityB on EntityA by setting the navigation ID to null. Strangely, the effect this has is that EntityA is marked for deletion when it’s EntityBId is set to null and when SaveChanges is called, it does infact delete EntityA.

This doesn’t make a whole lot of sense to me. Why would EntityA get deleted in this scenario? I’ve looked through the breaking changes in both EF Core 5 and EF Core 6 but I can’t see anything that would cause this.

I have tried switching the In-memory provider out for Sqlite but This exhibits the same strange behaviour.

Provider and version information

EF Core version: 6.0.0 Database provider: Microsoft.EntityFrameworkCore.InMemory and Microsoft.EntityFrameworkCore.Sqlite (both version 6.0.0) Target framework: . NET 6.0 Operating system: Windows 10 IDE: Rider 2021.3.1

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
AndriySvyrydcommented, Dec 13, 2021

Checking this is by-design?

Yes. If either the FK or the nav to principal is non-nullable then the relationship is required

1reaction
andyfurniss4commented, Dec 18, 2021

Thanks guys. You’ve cleared this up for me. I was pretty confused when this broke after upgrading but it makes sense now. I have made the appropriate changes to accommodate this default behaviour so please feel free to close this ticket.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why entity framework does not delete record when setting ...
Setting a navigation property to null will not delete the related entity. Note that there may be many navigation properties (different entities) ...
Read more >
Entity is deleted when Navigation property of the ...
SaveChanges for updated Entity with navigation property is reset to null results in Delete SQL statement for the entity.
Read more >
Saving Related Data - EF Core
You can remove a relationship by setting a reference navigation to null , or removing the related entity from a collection navigation. Removing ......
Read more >
Relationships, navigation properties, and foreign keys - EF6
The following code removes a relationship by setting the foreign key to null. Note, that the foreign key property must be nullable.
Read more >
How to access navigation property of deleted entity - eidias
When you remove an entity from the context its state is set to Deleted and all its navigation properties are nulled.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found