Skip to content

Fixed an issue with UpdateFromQuery/Async for string literals#164

Merged
NorthernLight1 merged 1 commit intoNorthernLight1:developmentfrom
PabloFerroDev:bug-in-updatefromquery-with-string-literals
Apr 29, 2026
Merged

Fixed an issue with UpdateFromQuery/Async for string literals#164
NorthernLight1 merged 1 commit intoNorthernLight1:developmentfrom
PabloFerroDev:bug-in-updatefromquery-with-string-literals

Conversation

@PabloFerroDev
Copy link
Copy Markdown
Contributor

When we want to update some value, for example using this:

await db.Users
     .Where(o => o.Id == requestAccount.Id)
     .UpdateFromQueryAsync(o => new Users { 
         Name = name,
         Surname = surname,
         Email = email,
         Initials = initials,
         Job = job,
         Password = newPassword,
         LastPasswordUpdate = DateTime.UtcNow
     });
     

and the e-mail is something like 'luciano.cravero@testmail.com', the 'o.' part is replaced to [Extent1], producing an update that does not respect the original string.

…ey contains "o." in some parts, for example "luciano.cravero@testmail.com"
Copy link
Copy Markdown
Owner

@NorthernLight1 NorthernLight1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of PR #164 - Fix UpdateFromQuery/Async string literal corruption

Fixes: Issue #165

Root Cause

The old code performed a naive string.Replace on the entire generated SQL expression, replacing the lambda parameter prefix (e.g. o.) with the table alias prefix (e.g. [Extent1].). This incorrectly mutated content inside SQL string literals - e.g. 'luciano.cravero@testmail.com' became 'lucian[Extent1].cravero@testmail.com'.

Fix Assessment

Core change in LinqExtensions.cs:

The new ReplaceOutsideSqlStringLiterals method uses a compiled regex ('(?:''|[^'])*') to split the SQL expression. Because the regex uses a capturing group, Regex.Split interleaves non-literal and literal segments [non-lit, lit, non-lit, ...]. Stepping i += 2 correctly applies the replacement only to non-literal segments.

Correctness checks:

  • Regex correctly matches SQL string literals including escaped single quotes ('')
  • Split interleaving behavior is correct for .NET's Regex.Split with capturing groups
  • Static + compiled regex is efficient for a potentially hot path
  • Unused using System.Threading.Tasks correctly removed and replaced with using System.Text.RegularExpressions

Tests

  • With_String_Containing_Dot - directly reproduces the reported bug
  • With_String_Column_Copy - regression guard ensuring column-reference expressions (where the dot must still be replaced) continue to work
  • Both sync and async variants covered

Minor Suggestion (non-blocking)

Consider adding a brief comment to ReplaceOutsideSqlStringLiterals explaining that Regex.Split with a capturing group interleaves captured/non-captured segments, making the i += 2 step non-obvious to future maintainers.


Verdict: Approved. The fix is minimal, targeted, and correct. Solid test coverage.

@NorthernLight1 NorthernLight1 merged commit 139cc75 into NorthernLight1:development Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants