DbUpdateException should not leave the context in a bad state
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
EF is wrongly adding (persisting) an entity when a duplicate key is found.
Consider the following Entity, when Name is set as Alternate Key:
```
public class MyEntity
{
[Key]
public int Id { get; set; }
// name is AlternateKey, set by modelBuilder
public string Name { get; set; }
public string SomeValue { get; set; }
}
```
Then consider the following scenario:
1. Add Entity1 with name "Foo".
2. SaveChanges -> Db is updated correctly and table now contains Entity1
3. Add Entity2 with name "Foo" -> exception is thrown (duplicate key) (see exception below)
4. Delete Entity1.
5. 5. Save Changes -> DB is updated so that Entity1 is deleted but **Entity2 is saved**!
One would not expect Entity1 to be saved after an error occured when adding it to the Dbset.
Yet, it looks like it is left in DbSet.Local and, with an Added State and is Added to the Db once Entity1 is removed.
Exception on step 3 is:
> Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
> ---> Microsoft.Data.SqlClient.SqlException (0x80131904): Violation of UNIQUE KEY constraint 'AK_MyEntities_Name'. Cannot insert duplicate key in object 'dbo.MyEntities'. The duplicate key value is (Foo).
> The statement has been terminated.
The following code simulates that process:
```
try
{
MyDbContext db = new MyDbContext();
MyEntity e1 = new MyEntity() { Name = "Foo", SomeValue = "Value1" };
db.MyEntities.Add(e1);
db.SaveChanges();
MyEntity e2 = new MyEntity() { Name = "Foo", SomeValue = "Value2" };
try
{
db.MyEntities.Add(e2);
}
catch (Exception ex)
// Exception is thrown here
{
Console.WriteLine(ex);
}
db.MyEntities.Remove(e1);
db.SaveChanges();
// e1 is deleted but e2 is persisted in the Db!
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
```
It seems the DbSet.Local is wrongly updated with the entity even though an exception was thrown during the call to .Add
A full console app sample project to reproduce this issue is attached.
--------------------------
EF Core version: 6.0.8
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
[EFDuplicateKey.zip](https://github.com/dotnet/efcore/files/9549424/EFDuplicateKey.zip)
Contributor guide
Assessment
This issue has not been assessed yet.