{"record":{"id":"a6d58b3e2d50e5bf","repo":"DapperLib/Dapper","slug":"the-member-name-of-type-type-fullname-cannot-b","errorCode":null,"errorMessage":"The member {name} of type {type.FullName} cannot be used as a parameter value","messagePattern":"The member (.+?) of type (.+?) cannot be used as a parameter value","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"Dapper/SqlMapper.cs","lineNumber":530,"sourceCode":"                }\r\n                return DynamicParameters.EnumerableMultiParameter;\r\n            }\r\n\r\n            switch (type.FullName)\r\n            {\r\n                case \"Microsoft.SqlServer.Types.SqlGeography\":\r\n                    AddTypeHandler(type, handler = new UdtTypeHandler(\"geography\"));\r\n                    return DbType.Object;\r\n                case \"Microsoft.SqlServer.Types.SqlGeometry\":\r\n                    AddTypeHandler(type, handler = new UdtTypeHandler(\"geometry\"));\r\n                    return DbType.Object;\r\n                case \"Microsoft.SqlServer.Types.SqlHierarchyId\":\r\n                    AddTypeHandler(type, handler = new UdtTypeHandler(\"hierarchyid\"));\r\n                    return DbType.Object;\r\n            }\r\n\r\n            if (demand)\r\n                throw new NotSupportedException($\"The member {name} of type {type.FullName} cannot be used as a parameter value\");\r\n            return DbType.Object;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Obtains the data as a list; if it is *already* a list, the original object is returned without\r\n        /// any duplication; otherwise, ToList() is invoked.\r\n        /// </summary>\r\n        /// <typeparam name=\"T\">The type of element in the list.</typeparam>\r\n        /// <param name=\"source\">The enumerable to return as a list.</param>\r\n        public static List<T> AsList<T>(this IEnumerable<T>? source) => source switch\r\n        {\r\n            null => null!,\r\n            List<T> list => list,\r\n            _ => Enumerable.ToList(source),\r\n        };\r\n\r\n        /// <summary>\r\n        /// Execute parameterized SQL.\r","sourceCodeStart":512,"sourceCodeEnd":548,"githubUrl":"https://github.com/DapperLib/Dapper/blob/72a54c475f75e18cb93cba0809d00a5e6e49efd9/Dapper/SqlMapper.cs#L512-L548","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npublic readonly struct Money { public decimal Amount; public string Currency; }\ncnn.Execute(\"insert orders(amount) values(@amount)\", new { amount = new Money(10, \"USD\") }); // throws\n\n// after — flatten to a primitive\ncnn.Execute(\"insert orders(amount) values(@amount)\", new { amount = money.Amount });\n// or register a handler:\nSqlMapper.AddTypeHandler(typeof(Money), new MoneyTypeHandler());","handlingStrategy":"validation","validationCode":"// Pre-flight: ensure every parameter member type is mappable or has a handler\nforeach (var p in param.GetType().GetProperties())\n{\n    var t = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType;\n    if (!SqlMapper.HasTypeHandler(t) && !IsPrimitiveMappable(t))\n        throw new NotSupportedException($\"Register a type handler for {t.FullName} before using it as a parameter\");\n}","typeGuard":"static bool IsPrimitiveMappable(Type t) =>\n    t.IsPrimitive || t.IsEnum || t == typeof(string) || t == typeof(decimal)\n    || t == typeof(DateTime) || t == typeof(Guid) || t == typeof(byte[]);","tryCatchPattern":"try { cnn.Execute(sql, param); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"cannot be used as a parameter value\"))\n{ /* register handler or project the member to a primitive, then retry */ }","preventionTips":["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."],"tags":["dapper","parameters","typehandler","notsupportedexception","mapping"],"backgroundTag":null,"analyzedSha":"72a54c475f75e18cb93cba0809d00a5e6e49efd9","analyzedAt":"2026-08-13T14:18:18.115Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}