DapperLib/Dapper · error · NotSupportedException
The member {name} of type {type.FullName} cannot be used as
Error message
The member {name} of type {type.FullName} cannot be used as a parameter value What it means
LookupDbType(type, name, demand, out handler) at SqlMapper.cs:461 walks Dapper's typeMap, registered type handlers, and special-case SQL Server UDTs (SqlGeography/SqlGeometry/SqlHierarchyId). If none match and demand is true, it throws NotSupportedException naming the member and its type (SqlMapper.cs:530). This is Dapper saying it has no idea how to turn the member into a parameter value.
Source
Thrown at Dapper/SqlMapper.cs:530
}
return DynamicParameters.EnumerableMultiParameter;
}
switch (type.FullName)
{
case "Microsoft.SqlServer.Types.SqlGeography":
AddTypeHandler(type, handler = new UdtTypeHandler("geography"));
return DbType.Object;
case "Microsoft.SqlServer.Types.SqlGeometry":
AddTypeHandler(type, handler = new UdtTypeHandler("geometry"));
return DbType.Object;
case "Microsoft.SqlServer.Types.SqlHierarchyId":
AddTypeHandler(type, handler = new UdtTypeHandler("hierarchyid"));
return DbType.Object;
}
if (demand)
throw new NotSupportedException($"The member {name} of type {type.FullName} cannot be used as a parameter value");
return DbType.Object;
}
/// <summary>
/// Obtains the data as a list; if it is *already* a list, the original object is returned without
/// any duplication; otherwise, ToList() is invoked.
/// </summary>
/// <typeparam name="T">The type of element in the list.</typeparam>
/// <param name="source">The enumerable to return as a list.</param>
public static List<T> AsList<T>(this IEnumerable<T>? source) => source switch
{
null => null!,
List<T> list => list,
_ => Enumerable.ToList(source),
};
/// <summary>
/// Execute parameterized SQL.
View on GitHub (pinned to 72a54c475f)
Solutions
- Register an ITypeHandler via SqlMapper.AddTypeHandler(type, handler) for the offending type.
- Project the parameter to a primitive Dapper understands before passing (e.g. myDomain.Value).
- Implement ICustomQueryParameter on the type so Dapper can build the DbParameter directly.
- For enums, ensure the underlying type is mapped or enable Settings.PreferTypeHandlersForEnums with a handler.
Example fix
// before
public readonly struct Money { public decimal Amount; public string Currency; }
cnn.Execute("insert orders(amount) values(@amount)", new { amount = new Money(10, "USD") }); // throws
// after — flatten to a primitive
cnn.Execute("insert orders(amount) values(@amount)", new { amount = money.Amount });
// or register a handler:
SqlMapper.AddTypeHandler(typeof(Money), new MoneyTypeHandler()); Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: ensure every parameter member type is mappable or has a handler
foreach (var p in param.GetType().GetProperties())
{
var t = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType;
if (!SqlMapper.HasTypeHandler(t) && !IsPrimitiveMappable(t))
throw new NotSupportedException($"Register a type handler for {t.FullName} before using it as a parameter");
} Type guard
static bool IsPrimitiveMappable(Type t) =>
t.IsPrimitive || t.IsEnum || t == typeof(string) || t == typeof(decimal)
|| t == typeof(DateTime) || t == typeof(Guid) || t == typeof(byte[]); Try / catch
try { cnn.Execute(sql, param); }
catch (NotSupportedException ex) when (ex.Message.Contains("cannot be used as a parameter value"))
{ /* register handler or project the member to a primitive, then retry */ } Prevention
- Register ITypeHandler for custom value types before first query.
- Project domain objects to primitives in the anonymous param.
- Implement ICustomQueryParameter on types that build their own DbParameter.
- Keep a whitelist of allowed parameter types and validate at app start.
When it happens
Trigger: Pass an anonymous object / POCO parameter whose property is a type Dapper cannot map: a complex class, an unregistered struct, an interface, or a custom type with no ITypeHandler. Parameter materialization calls LookupDbType with demand=true for each member.
Common situations: Custom value types or domain objects used as parameters without registering a type handler; passing a navigation property / nested entity object as a param; enums whose underlying type is not in the map; third-party types (e.g. NodaTime, System.Text.Json elements) without a handler.
Related errors
- An enumerable sequence of parameters (arrays, lists, etc) is
- When passing parameters by position, each parameter can only
- The first item in a list-expansion cannot be null
- ValueTuple should not be used for parameters - the language-
- MultiExec is not supported by ExecuteReader
AI-assisted analysis of DapperLib/Dapper@72a54c475f (2026-08-13).
Data as JSON: /api/errors/a6d58b3e2d50e5bf.
Report an issue: GitHub.