API proposal: custom interpolated string handler
@mgravell is already working on this.
Since Dec 14, 2024.
- Dominant language
- C#
- Stars
- 18.4k
- Forks
- 3.7k
- Avg merge
- 5h 8m
- Merged PRs (30d)
- 1
Description
Right now, the preferred way of passing args to Dapper requires a second parameter, for example:
string name = ...
int id = ...
conn.Execute("""
update customer
set name = @name
where id = @id
""", new { name, id });
This works; Dapper (vanilla) has code to emit custom per-type code to extract the parameters, and DapperAOT has additional code to pre-gen that as AOT and better validation (mismatched args etc). Additional per-value parameter settings are awkward, but overall: it works.
However!
There is also a possibility to use a custom "interpolated string handler". I have a fully working prototype that allows the following:
string name = ...
int id = ...
conn.Execute($"""
update customer
set name = @{name}
where id = @{id}
""");
This is not a string, and is zero alloc, fully parameterized (SQLi safe), etc. Note that the leading @ (or : etc) is primarily because ADO.NET does not directly expose the parameter token of a given connection, but IMO it helps make it very clear what is going on.
Under the hood, this emits fundamentally the same SQL, even using the argument-expression feature to generate sensible parameter names where possible (name and id in this case). Additionally, from .NET 9 the "alt-lookup" feature of dictionaries is used to avoid allocating a new string per usage. There is zero runtime ref-emit etc needed for packing parameters - we basically trick the C# compiler into doing that work for us!
We could also potentially use the optional format parameters to convey other information, for example:l {name:1000} could set the .Size to 1000, and {qty:P=5,S=3} could set the .Precision and .Scale.
Genuine question: is this an improvement? Is this worth adding new overloads of some core methods? Is this technically nice but not worth the mental addition? Or is this hell-yeah-lets-do-this?
Separately, an analyzer in AOT is proposed to spot interpolated string uses that are susceptible to SQLi (i.e. the type is string); I would also propose that we start shipping Dapper.Advisor inside Dapper, to light up all those checks by default.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.