-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EF Core marks entities removed From child collections as modified #10093
Comments
@timmhagen You don't show what the Child class looks like, but I expect that the FK on the child is nullable such that when the parent is deleted the child FKs are nulled out, resulting in their state being deleted. (Note that if there is no FK property in your class, then EF creates a "shadow" property which is by default nullable.) To get a required relationship (non-nullable FK), use the |
@ajcvickers The code was generated using DB First, due to existing database. There is a mapping in the database for the Parent/Child relationship. I looked at Child (Dossier) and it didn't have the .IsRequired(). In this case my Parent is Event and the Child is Dossier. modelBuilder.Entity(entity => In the Event Entity Class there is a property public ICollection Dossier { get; set; } |
@timmhagen At this point I think we will need a full project or code listing that reproduces what you are seeing. From the snippets you have posted, the entities should change from Modified to Deleted while SaveChanges is running and the deletes should be sent to the database. (Note that the code you have above will not show the entities as Deleted because the cascade won't happen until base.SaveChanges is called, but you should still see delete statements sent to the database.) |
@ajcvickers I tried to recreate the issue with the Northwind database and I don't get the same behavior when deleting collections, in my Demo app the state comes back Deleted. I will have to dig more into the differences between on how Order and OrderDetails relate compared to how my Database Entities Event and Dossier relate. I thought maybe it had to do with changing from ClientSetNull to Cascade but I tried the same thing with Northwind and it still show Deleted state. Thanks for your help, sorry it ended up being something goofy in my configuration. |
@ajcvickers Ok. I have narrowed it down to the difference and was able to replicate it in a demo project. The issue is when a Parent has a Child who has a Child of its own. I tried to incorporate my Demo using the Northwind Database so my tables and demo code are pretty rough and crude but demonstrates what I am seeing. In my Demo I had to change up my relationships from above to kinda make sense in my head and to work with the Northwind database. I have Parent of Orders with many Events who in turns has many Locations. In my Demo I pull an Order, then grab an Event, then Remove that item from the Order's Event Collection. I expected the state to be Deleted for Event Entity but it came back as Modified. I think this has to do with the Cascading Delete of Locations on the Event Entity. Demo DELETE Endpoint |
@timmhagen Can you clarify whether the problem you are describing is that the entities don't show up as "Deleted" or that they don't actually get deleted? What I am seeing with the repro code is this:
This is all seems to be working as expected in the repro code. If the issue is that you are just not seeing entities marked as Deleted, this is because cascade deletes happens while SaveChanges is running which means in your code will not see this state as it looks at the state before SaveChanges has executed. I have been intending for a while to file an enhancement issue to make it possible to configure this--I'll do that now. |
See #10114 |
@ajcvickers Sorry I forgot to check what EF DB First Scaffolded out in the Demo for the dbContext for that Entity and made the assumption I changed it to Cascade. In my apps code which I was trying to pull a demo out of it does a Cascade Delete. To answer your question. The entities do get deleted in the database but when checking the change tracking, prior to the Base.SaveChanges, for cases where they are deleted I was only getting modified where I expected to see Deleted for the Entity I removed and any cascading ones. From what I can gather in #10114 I believe that is related. |
@ajcvickers In the case where ClientSetNull you made mention of still Event being set to Modified, I would have expected that Event would still be Deleted because the Entity was removed and that Orders would be marked Modified (if anything). If the entity being removed is marked Modified how would I know if it was deleted vs just edited? |
@timmhagen There isn't any easy way to do this right now--that's why I filed #10114. You could take a look at the code in StateManager.GetInternalEntriesToSave() and InternalEntityEntry.CascadeDelete and replicate this logic in your code. |
We're hitting this exact issue. Has there been any updates on the possible fix? Not being able to reliably have the State of entities being processed by the database context is becoming a very large hurdle for us, and writing a custom solution seems silly when this behavior appears to be a bug in the implementation. |
@joshjreed The only actionable item that came out of this issue is tracked by #10114, which is not currently scheduled for the 2.1 release. If you are seeing something that is not covered by that issue, then please file a new issue with a runnable project/solution or complete code listing that demonstrates the behavior you are seeing. |
Thanks @ajcvickers. The issue we're seeing is that entities show with a "Modified" state but no changes, when in reality they are being deleted. Because we can't trust the state being shown, we can't correctly deal with those entities. Will we be able to see a correct state on these entities as a result of #10114? If so, that will cover our needs. |
@joshjreed Yes, that issue will allow cascading deletes to happen before SaveChanges, so you will be able to see the final states at that time. |
Hi guys, I had the same issue. I have fixed with a couple of extension methods based on @ajcvickers recommendations. public static void ApplyCascadeDeletes<T>(this IEnumerable<EntityEntry<T>> entities) where T : class
{
foreach (var entry in entities.Where(
e => (e.State == EntityState.Modified
|| e.State == EntityState.Added)
&& e.GetInternalEntityEntry().HasConceptualNull).ToList())
{
entry.GetInternalEntityEntry().HandleConceptualNulls();
}
foreach (var entry in entities.Where(e => e.State == EntityState.Deleted).ToList())
{
entry.GetInternalEntityEntry().CascadeDelete();
}
} public static InternalEntityEntry GetInternalEntityEntry<T>(this EntityEntry<T> entityEntry) where T : class
{
var internalEntry = (InternalEntityEntry)entityEntry
.GetType()
.GetProperty("InternalEntry", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(entityEntry);
return internalEntry;
} |
Seems like InternalEntry. CascadeDelete() has been removed from Ef core 2.1. So @jruizx 's workaround would not work as is. |
Hi @sellomkantjwa, on my website I have added a fix for EF Core 2.1 https://comment-it.co.uk/entity-framework-core-soft-delete-workaround/ |
Hi, I don't know if this is the same issue, but seems very similar. I have a parent with a collection of child elements. I remove a child, and in SaveChanges, I iterate over changes. My code handles soft deletes by finding any entities with state Deleted and instead setting them to Modified with IsDeleted=true. BTW your fix, the 2.1 version above, @jruizx , fixes it... but is this an EF Core bug that will be fixed? |
3 years have passed but the issue still exists in EF Core 3.1. The navigation property I want to delete is marked as |
If you are using EF core 2 for SQL Server, and you remove an entity from a child collection in a Parent,, EF sets the state of the deleted entity to be Modified, but it does delete the entity from the DB when you call SaveChanges. I am hooking into the SaveChanges event to do the check.
I expect that the state would be Deleted for the Child, but when checking state in my Event hook for SaveChanges, it shows as modified, not deleted.
Further technical details
PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0"
PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0"
PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.0"
Operating system: Windows 7
IDE: Visual Studio 2017 CE
The text was updated successfully, but these errors were encountered: