dotnet/efcore · error · InvalidOperationException
SqlQueryUnmappedType
SqlQueryUnmappedType
Error message
The element type '{elementType}' used in 'SqlQuery' method is not natively supported by your database provider. Either use a supported element type, or use ModelConfigurationBuilder.DefaultTypeMapping to define a mapping for your type. What it means
In the SqlQueryRootExpression case (line 215-251), EF looks up a relational type mapping for the element type via the type mapping source. Raw SQL queries (SqlQueryRaw/SqlQuery<T>) require each element to be a type the provider can map to a single column. If FindMapping returns null, SqlQueryUnmappedType is thrown, suggesting DefaultTypeMapping configuration.
Source
Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs:222
Check.DebugAssert(
!subquerySourceSelectExpression.HasNonEntityNullabilityMarkers,
"Non-grouping subquery clone carries a live non-entity nullability marker; it would be stranded by Clone(). "
+ "Route it through a marker-aware remap as the GroupByShaperExpression case does.");
var clonedSelectExpression = subquerySourceSelectExpression.Clone();
return new ShapedQueryExpression(
clonedSelectExpression,
new QueryExpressionReplacingExpressionVisitor(shapedQueryExpression.QueryExpression, clonedSelectExpression)
.Visit(shapedQueryExpression.ShaperExpression));
case SqlQueryRootExpression sqlQueryRootExpression:
{
var typeMapping = RelationalDependencies.TypeMappingSource.FindMapping(
sqlQueryRootExpression.ElementType, RelationalDependencies.Model);
if (typeMapping == null)
{
throw new InvalidOperationException(
RelationalStrings.SqlQueryUnmappedType(sqlQueryRootExpression.ElementType.DisplayName()));
}
var alias = _sqlAliasManager.GenerateTableAlias("sql");
var selectExpression = new SelectExpression(
[new FromSqlExpression(alias, sqlQueryRootExpression.Sql, sqlQueryRootExpression.Argument)],
new ColumnExpression(
SqlQuerySingleColumnAlias,
alias,
sqlQueryRootExpression.Type.UnwrapNullableType(),
typeMapping,
sqlQueryRootExpression.Type.IsNullableType()),
identifier: [],
_sqlAliasManager);
Expression shaperExpression = new ProjectionBindingExpression(
selectExpression, new ProjectionMember(), sqlQueryRootExpression.ElementType.MakeNullable());
View on GitHub (pinned to dbf9771522)
Solutions
- Use a natively supported primitive type (int, long, string, Guid, DateTime, decimal, etc.) as the element type.
- Register a mapping for your custom type via ModelConfigurationBuilder.DefaultTypeMapping<T>() in OnModelCreating/Configure.
- Map the result to an entity type and query the DbSet instead, or project scalar columns separately.
Example fix
// before (custom struct has no mapping)
var ids = db.Database.SqlQueryRaw<MyCustomId>("SELECT id FROM t");
// after (use a supported primitive, or register a mapping)
var ids = db.Database.SqlQueryRaw<int>("SELECT id FROM t");
// or, in model configuration:
// configurationBuilder.DefaultTypeMapping<MyCustomId>(); Defensive patterns
Strategy: validation
Validate before calling
// Confirm the element type has a relational mapping before calling SqlQuery<T>.
var mapping = db.GetService<IRelationalTypeMappingSource>().FindMapping(typeof(T));
if (mapping is null) throw new InvalidOperationException($"No mapping for {typeof(T)}; use a primitive or register DefaultTypeMapping."); Type guard
// Restrict SqlQuery element types to provider-supported primitives at compile time.
static bool IsSupportedElementType(Type t) =>
t == typeof(int) || t == typeof(long) || t == typeof(string)
|| t == typeof(Guid) || t == typeof(DateTime) || t == typeof(decimal)
|| t == typeof(double) || t == typeof(bool); Try / catch
try { var rows = await db.Database.SqlQueryRaw<T>(sql).ToListAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("not natively supported"))
{ /* switch T to a primitive, or register DefaultTypeMapping<T> */ } Prevention
- Use primitive scalar types as SqlQuery<T> element types.
- Register custom types via ModelConfigurationBuilder.DefaultTypeMapping<T>.
- Remember SqlQuery<T> maps T to a single column; query entities via DbSet for multi-column results.
When it happens
Trigger: Calling context.Database.SqlQueryRaw<T>(sql) or SqlQuery<T>(sql) where T is not a natively supported primitive (int, string, DateTime, etc.) and has no configured mapping — e.g. a custom struct, a complex object, or an unmapped enum.
Common situations: Using SqlQuery<T> with a custom value type or DTO that the provider does not know how to read from a single result column; forgetting that SqlQuery<T> maps T to one column (unlike entity queries); provider that lacks a mapping for an uncommon primitive (e.g. some numeric/decimal variants).
Related errors
- Model building is not supported when publishing with NativeA
- Model building is not supported when publishing with NativeA
- Unable to find a store type mapping for column '{table}.{col
- The partition key value is of type '{valueType}' which is no
- The expression '{sqlExpression}' in the SQL tree does not ha
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/2badd21465ecd79a.
Report an issue: GitHub.