Fixed an issue with UpdateFromQuery/Async for string literals#164
Conversation
…ey contains "o." in some parts, for example "luciano.cravero@testmail.com"
NorthernLight1
left a comment
There was a problem hiding this comment.
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.Taskscorrectly removed and replaced withusing System.Text.RegularExpressions
Tests
With_String_Containing_Dot- directly reproduces the reported bugWith_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.
When we want to update some value, for example using this:
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.