* Add Settings.PreferTypeHandlersForEnums opt-in flag
When enabled, Dapper checks for a registered TypeHandler for enum types
before falling back to the default integer boxing behavior. This allows
custom enum serialization (e.g. storing enums as strings via TypeHandlers)
to work on both reads and writes.
Patched locations:
- LookupDbType: return DbType.Object with handler when flag is on
- CreateParamInfoGenerator: skip integer boxing when handler exists
- GetSimpleValueDeserializer: route to TypeHandler before Enum.ToObject
- Parse<T>: route to TypeHandler before Enum.ToObject
Default is false — zero behavior change for existing users.
* Patch IL-emitted type deserializer and add tests
- Fix 6th enum-before-handler location in GetTypeDeserializer IL emit,
preserving Nullable<T> wrapping for nullable enum properties
- Fix em-dash in comment (non-ASCII)
- Add two tests: round-trip write+read via StringEnumHandler, and
nullable enum with null value
* Update SDK version from 10.0.102 to 8.0.100
* Update global.json
we have fixed the CI glitch separately
---------
Co-authored-by: Marc Gravell <marc.gravell@gmail.com>
The IL emitted by CreateParamInfoGenerator used Callvirt to invoke
AddParameter on an unboxed struct sitting on the evaluation stack.
Callvirt expects a reference, so the CLR misinterpreted the raw struct
bytes as an object pointer, causing a fatal CLR error (0x80131506).
* - mark AddTypeHandlerImpl as obsolete
- syncronize type-handler mutates, to prevent lost writes
* CI: revert pgsql uddate
* suppress Impl's use of clone: false
* avoid additional local snapshot, now that we're synchronized
* explicitly request postgresql96
* more pgsql poking
* pg path fix
* see #2115
- correctness: do no use SingleRow by default; affects trailing errors
- performance: QueryUnbufferedAsync can mirror cmd?.Cancel() in finally (this is consistent with all other scenarios)
* remove settings tweak
When disposing wrapped readers, only call Dispose() on the inner reader and let it catch exceptions if appropriate.
Note: this actually happened with `Microsoft.Data.SqlClient`.
```
Microsoft.Data.SqlClient.SqlException (0x80131904): Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
---> System.ComponentModel.Win32Exception (258): The wait operation timed out.
at void Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, bool breakConnection, Action<Action> wrapCloseInAction)
at void Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, bool callerHasConnectionLock, bool asyncClose)
at bool Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, out bool dataReady)
at bool Microsoft.Data.SqlClient.SqlDataReader.TryCloseInternal(bool closeReader)
at void Microsoft.Data.SqlClient.SqlDataReader.Close()
at void Dapper.DbWrappedReader.Dispose(bool disposing) in /_/Dapper/WrappedReader.cs:line 149
at ValueTask System.Data.Common.DbDataReader.DisposeAsync()
```
* string and byte[] : add UseGetFieldValue to prevent problems with npgsql using global deserializer
* switch to GetFieldValue<T> changes some messaging in invalid cast scenarios; if anything, new version is clearer, so: fine
* test fixes