Skip to main content

Fixed: "Unknown column 's.Value' in 'field list'" with EF Core SqlQuery

· 4 min read
Jagdish Kumawat
Founder @ Dewiride

SELECT VERSION() is about the simplest query there is, and db.Database.SqlQuery<string>(...).FirstAsync() failed with Unknown column 's.Value' in 'field list'. My SQL has no s and no Value. EF Core added both, and it expects one thing from you.

What I Was Doing​

In my .NET C# Web API, with EF Core 10.0.14 and MySQL 9.7.4, I wanted the server's version:

An endpoint
g.MapGet("/raw/sqlquery-noalias", async (InventoryDbContext db, CancellationToken cancellationToken) =>
{
var version = await db.Database
.SqlQuery<string>($"SELECT VERSION()")
.FirstAsync(cancellationToken);

return Results.Ok(new { version });
});

What I Expected​

9.7.4.

What I Got​

Response
HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json

{
"type": "https://tools.ietf.org/html/rfc9110#section-15.6.1",
"title": "An error occurred while processing your request.",
"status": 500,
"traceId": "00-53dd17c58a91330c55b721b19f46c539-cba76e2545779846-00"
}
API log
SELECT `s`.`Value`
FROM (
SELECT VERSION()
LIMIT 1
MySql.Data.MySqlClient.MySqlException (0x80004005): Unknown column 's.Value' in 'field list'

The log showing the SQL EF Core sent, with a subquery aliased s, and MySqlException: Unknown column 's.Value' in 'field list'.

What I Checked​

The SQL EF Core sent. It's in the log above: my statement became a subquery called s, and FirstAsync selects s.Value from it.

The docs. The SQL queries page says: "You can also compose LINQ operators over your SQL query. However, since your SQL becomes a subquery whose output column needs to be referenced by the SQL EF adds, you must name the output column Value."

Why It Happens​

FirstAsync is a LINQ operator, so EF Core composes over your SQL, and it needs to refer to your column by name. It has settled on Value. With no alias, MySQL names the column VERSION(), so s.Value doesn't exist.

The Fix​

Name the column Value:

An endpoint
g.MapGet("/raw/sqlquery", async (InventoryDbContext db, CancellationToken cancellationToken) =>
{
var version = await db.Database
.SqlQuery<string>($"SELECT VERSION() AS Value")
.FirstAsync(cancellationToken);

var connectionId = await db.Database
.SqlQuery<ulong>($"SELECT CONNECTION_ID() AS Value")
.FirstAsync(cancellationToken);

return Results.Ok(new { version, connectionId });
});

After the Fix​

Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
"version": "9.7.4",
"connectionId": 117
}

A response of 200 OK with version 9.7.4.

Common Mistakes​

MistakeWhat happensDo this instead
Using ToListAsync to avoid itIt works, until someone adds WhereAdd the alias anyway
Using a DTO's property names and Value togetherThe alias must match the typeValue for scalars, property names for DTOs
Building the SQL with string concatenationIt opens the door to SQL injectionUse the interpolated form, which makes parameters

Troubleshooting​

SymptomLikely causeFix
Unknown column 's.Id'A DTO's property has no matching columnAlias it to the property's name
It fails only after adding a filterFilters compose tooAdd the alias
The value can't be convertedThe type doesn't match, such as int for BIGINTUse long or ulong

Conclusion​

SqlQuery<T> with a scalar type expects a column named Value as soon as you add a LINQ operator. Add AS Value to your SQL.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.