dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.82k stars 3.2k forks source link

Warn if a non-key property is configured as PropertySaveBehavior.Throw #23786

Open roryap opened 3 years ago

roryap commented 3 years ago

See attached project. I am trying to make it so an exception is thrown when a change is made to a certain property after the initial insert. I'm using entity.Property(nameof(MyClass.Name)).Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Throw); but the save is successful (no ex) and the property remains unchanged.

EF Core PropertySaveBehavior.Throw Issue.zip

EF Core version: 5.0.1 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET Core 3.1 Operating system: Windows 10 Pro (1.0.19042) IDE: Visual Studio 2019 16.8.2

ajcvickers commented 3 years ago

@roryap The problem here is that EF Core doesn't actually know whether or not the property has been modified or not. This is because entity to be updated is changed while it is not being tracked, and then it is tracked again with a call to Update. Update marks all properties as modified, except that it skips those properties that should not normally be included in a database update. This isn't ideal, but doing otherwise would cause SaveChanges to always throw, which also isn't ideal.

This works correctly if:

I'm been writing a lot about this recently in the new docs on change tracking--PR here: https://github.com/dotnet/EntityFramework.Docs/pull/2972

We will discuss this behavior, since I agree it is confusing. It may be worthwhile to output a warning if Update is used and any values other than keys are marked as AfterSave.Throw.

roryap commented 3 years ago

A warning would be great. Just something to trigger some behavior, e.g. throwing my own exception. I'm (obviously) using it in a disconnected way, which I cannot change.

ajcvickers commented 3 years ago

Note from triage: we will warn if a non-key property is marked to throw after save, but then an attempt is made to set all properties as modified.