This feels like a bug in the SQL query optimizer rather than Dapper.
It ought to be smart enough to convert a constant parameter to the target column type in a predicate constraint and then check for the availability of a covering index.
It's the optimizer caching the query plan as a parameterized query. It's not re-planning the index lookup on every execution.
How do you safely convert a 2 byte character to a 1 byte character?
There's a data type precedence that it uses to determine which value should be casted[0]. Nvarchar is higher precedence, therefore the varchar value is "lifted" to an nvarchar value first. This wouldn't be an issue if the types were reversed.
0: https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-...