-
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
Incorrect Entries Values in DbUpdateException when an error occurs in the SQL MERGE statement during insert #29379
Comments
@roji or @AndriySvyryd Can you take a look at this? Looks like |
@roji Ping for potentially fixing this in a patch. |
Unfortunately, it's impossible to make DbUpdateException.Entries contain the right entry for SQL Server bulk insert scenarios. As a reminder, EF Core 6.0 generated the following SQL (also generated by 7.0 for trigger scenarios): DECLARE @inserted1 TABLE ([Id] int, [_Position] [int]);
MERGE [Books] USING (
VALUES (@p1, @p2, @p3, 0),
(@p4, @p5, @p6, 1),
(@p7, @p8, @p9, 2),
(@p10, @p11, @p12, 3)) AS i ([BookStoreId], [Number], [Title], _Position) ON 1=0
WHEN NOT MATCHED THEN
INSERT ([BookStoreId], [Number], [Title])
VALUES (i.[BookStoreId], i.[Number], i.[Title])
OUTPUT INSERTED.[Id], i._Position
INTO @inserted1;
SELECT [i].[Id] FROM @inserted1 i
ORDER BY [i].[_Position]; The rows coming back from the databases are ordered by position, so EF naturally knows which row corresponds to which entry. EF Core 7.0 stopped using the temporary table, and so cannot apply ordering to the MERGE results; instead, we return the position as an output column: MERGE [Books] USING (
VALUES (@p1, @p2, @p3, 0),
(@p4, @p5, @p6, 1),
(@p7, @p8, @p9, 2),
(@p10, @p11, @p12, 3)) AS i ([BookStoreId], [Number], [Title], _Position) ON 1=0
WHEN NOT MATCHED THEN
INSERT ([BookStoreId], [Number], [Title])
VALUES (i.[BookStoreId], i.[Number], i.[Title])
OUTPUT INSERTED.[Id], i._Position; But if there's an exception, the row containing the position is never read (DbDataReader.Read raises the exception), so we cannot know which entry triggered it. We should still correct the behavior to return |
It should contain all entities in the batch, including the correct one |
Entities and DbContext
Setup
Generated SQL
If you are catching a DbUpdateException, because of a SqlException (UniqueKey violation), the
DbUpdateException.Entries
will be deliver only the first entity, if the insert statement was a SQL MERGE Statement.Output:
If you only insert 3 books and the
Books
table is configured with a trigger (-> NO MERGE STATEMENT) - it will work:Correct Output:
In our production environment we also had the case that even the wrong entity was delivered. In this case - a BookStore entity instead of the Book entity. However, I could not reproduce this scenario in this example.
Include provider and version information
EF Core version: 7.0 RC1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0 / .NET 7.0
Operating system: Windows 11
IDE: Visual Studio 2022 17.3.6
The text was updated successfully, but these errors were encountered: