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)
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
EF Core version: 3.0.1
Database provider: Npgsql
Target framework:.NET Core 3.0
Operating system: Windows 10 Pro
IDE: JetBrains Rider
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.
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?