Efcore: Detaching an entity results in related entities being deleted

Created on 19 Nov 2019  路  8Comments  路  Source: dotnet/efcore

EF Core 3.0.1

I insert an object along with related objects. Then I set the state of the object to "Detached". I then perform another call to .SaveChangesAsync().

Observed behavior: the related objects are deleted.
Expected behavior: the related objects should not be deleted; rather their tracking status should simply be set to "Detached".

(This is a breaking change since upgrading from EF Core 2.2.4)

Steps to reproduce

    public class Thing
    {
        [Key]
        public Guid ThingId { get; set; }
        [MaxLength(200)]
        public string Description { get; set; }
        public List<OwnedByThing> OwnedByThings { get; set; } = new List<OwnedByThing>();
    }

    public class OwnedByThing
    {
        [Key]
        public Guid OwnedByThingId { get; set; }
        public Guid ThingId { get; set; }
        public Thing Thing { get; set; }
        public int Value { get; set; }
    }

            await using var db = new MyDbContext();
            var thing = new Thing
            {
                Description = "Hello world thing",
                OwnedByThings = new List<OwnedByThing>
                {
                    new OwnedByThing {Value = 1},
                    new OwnedByThing {Value = 2}
                }
            };

            db.Things.Add(thing);
            await db.SaveChangesAsync();

            var thingCount = await db.Things.CountAsync(e => e.ThingId == thing.ThingId);
            Assert.AreEqual(1, thingCount, "Thing Count A");
            var ownedCount = await db.OwnedByThings.CountAsync(e => e.ThingId == thing.ThingId);
            Assert.AreEqual(2, ownedCount, "Owned count A");

            db.Entry(thing).State = EntityState.Detached;
            await db.SaveChangesAsync();

            thingCount = await db.Things.CountAsync(e => e.ThingId == thing.ThingId);
            Assert.AreEqual(1, thingCount, "Thing Count B");
            ownedCount = await db.OwnedByThings.CountAsync(e => e.ThingId == thing.ThingId);
            Assert.AreEqual(2, ownedCount, "Owned count B");

Result:

  Owned count B
  Expected: 2
  But was:  0

Further technical details

EF Core version: 3.0.1
Database provider: Npgsql
Target framework:.NET Core 3.0
Operating system: Windows 10 Pro
IDE: JetBrains Rider

Servicing-approved closed-fixed customer-reported type-bug

Most helpful comment

@shaulbehr It looks like a workaround might be to revert the change to the cascade timing using something like this:
C# public BloggingContext() { ChangeTracker.CascadeDeleteTiming = CascadeTiming.OnSaveChanges; ChangeTracker.DeleteOrphansTiming = CascadeTiming.OnSaveChanges; }
Can you test if this workaround works for you?

All 8 comments

Hello, has anyone noticed this? I'd say this is a pretty serious bug, no?

Note for triage: this still repros with 3.1. It looks like detaching the principal is causing cascade delete of the dependents rather than cascade detach.

@shaulbehr We will investigate whether this is something we should patch.

@shaulbehr It looks like a workaround might be to revert the change to the cascade timing using something like this:
C# public BloggingContext() { ChangeTracker.CascadeDeleteTiming = CascadeTiming.OnSaveChanges; ChangeTracker.DeleteOrphansTiming = CascadeTiming.OnSaveChanges; }
Can you test if this workaround works for you?

@ajcvickers Yep, that workaround works. Thanks!

Please fix this soon as possible!
I was not aware of this problem and I already lost data because of this problem!
This is a way to work!
I shouldn鈥檛 have to came here to know that you already found the problem 3 months ago and simply post an workaround instead of fixing it and relesse the fix in 3.1 or 3.1.1 etc.
I thought you were having short release cycles so you could deliver this kind of fixes fast!
Nothing in the breaking changes tell us about this side effect of the detach!
I am very frustated with this.

For me the Expected behavior is the related objects should not be deleted; rather their tracking status should REMAIN the same - it shouldn鈥檛 be affected - it鈥檚 the beahvior of EF6 and EFCore 2.2.
Exemple: if the related object state is Added it should continue with that state!

Thanks

@silvajpr This is approved for the 3.1.3 patch, tentatively scheduled for March.

@ajcvickers do you have an ETA for 3.1.3 patch release?

@YZahringer It's still tentatively scheduled for March.

Was this page helpful?
0 / 5 - 0 ratings