Search code examples
c#sql-serverentity-framework-coreasp.net-core-webapisqlexception

Why is DbContext.SaveChangesAsync throwing a "Subquery returned more than 1 value" error?


The error in the title is occurring only in my QA environment right now, and not in my DEV environment. I've pointed my local machine towards the QA environment, ran a SQL trace, and can 1) reproduce the error and 2) see the actual SQL code being generated.

What I don't understand is how in the hell an error like this is even possible on an update? Here's my code:

            var investigation = await (
                        from  ti in DbContext.Investigation
                        where ti.Id == model.InvestigationId
                        select ti
                    ).SingleAsync();

            investigation.QueueId = model.QueueId;

            var result = await DbContext.SaveChangesAsync();

            return result;

I initially thought that first line (query) was returning more than one result, which would make sense. However, the error occurs on the var result = await DbContext.SaveChangesAsync(); line. Could someone please point me in the right direction to resolve this? My SQL query as picked-up by SQL Server Profiler:

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Investigation] SET [QueueId] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;

',N'@p1 bigint,@p0 smallint',@p1=7863,@p0=4

Solution

  • There is no subquery in this problem code as the error message suggests:

    exec sp_executesql N'SET NOCOUNT ON;
    UPDATE [Investigation] SET [QueueId] = @p0
    WHERE [Id] = @p1;
    SELECT @@ROWCOUNT;
    ',N'@p1 bigint,@p0 smallint',@p1=7863,@p0=4
    

    Consequently, the error must be in trigger code fired by the UPDATE statement.

    I see from your comment that extraneous INSERT statements were inadvertently included in the trigger code. A more common cause of these symptoms is that the trigger is improperly coded as to expect a single row to be affected. A trigger fires once per statement, not per row, so it is important that trigger code handle the possibility of multiple rows.