dotnet/efcore · error · NotSupportedException
A DbCommand cannot be created for a non-relational query.
Error message
A DbCommand cannot be created for a non-relational query.
What it means
CreateDbCommand throws NotSupportedException with NoDbCommand when the query's executable is not an IRelationalQueryingEnumerable. This means the IQueryable was produced by a non-relational provider (in-memory, or a third-party non-relational provider) or has been wrapped in a way that hides the relational querying enumerable. The method exists to expose the DbCommand EF would execute, so a non-relational backend has nothing to return.
Solutions
- Ensure the DbContext is configured with a relational provider (UseSqlServer, UseNpgsql, UseSqlite, etc.) at runtime.
- Switch integration tests to a real relational provider (UseSqlite with in-memory connection) so CreateDbCommand works.
- Guard with `query.Provider is IRelationalQueryingEnumerable` or try/catch NotSupportedException when the method is optional.
Example fix
// before
options.UseInMemoryDatabase("tests");
...
var cmd = db.Blogs.CreateDbCommand();
// after — use SQLite in-memory for relational semantics
options.UseSqlite("DataSource=:memory:");
var cmd = db.Blogs.CreateDbCommand(); Defensive patterns
Strategy: validation
Validate before calling
if (query.Provider.Execute<IEnumerable>(query.Expression) is IRelationalQueryingEnumerable)
var cmd = query.CreateDbCommand();
else
throw new InvalidOperationException("Query is not relational; cannot create DbCommand."); Type guard
static bool IsRelational(IQueryable q)
=> q.Provider.Execute<IEnumerable>(q.Expression) is IRelationalQueryingEnumerable; Try / catch
try { var cmd = query.CreateDbCommand(); }
catch (NotSupportedException ex) when (ex.Message.Contains("non-relational"))
{
// skip DbCommand inspection in test/in-memory runs
} Prevention
- Use a real relational provider (e.g. SQLite in-memory) when tests need CreateDbCommand.
- Avoid InMemoryProvider for assertions about generated SQL.
- Guard CreateDbCommand calls when the provider may vary by environment.
When it happens
Trigger: Calling queryable.CreateDbCommand() on a query built against DbContextOptions.UseInMemoryDatabase, a test double, or a provider that does not implement IRelationalQueryingEnumerable. Also when LINQ operators fully evaluated client-side leave no relational enumerable behind.
Common situations: Test suites using InMemory provider for speed then calling CreateDbCommand for assertion; mixing provider configurations conditionally; a provider upgrade that changed the querying-enumerable type; calling CreateDbCommand on a cached or enumerated IQueryable.
Related errors
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/9ce3b6662c612fe0.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs:44
/// executed the command.
/// </para>
/// <para>
/// Note that DbCommand is an <see cref="IDisposable" /> object. The caller is responsible for disposing the returned
/// command.
/// </para>
/// <para>
/// This is only typically supported by queries generated by Entity Framework Core.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-diagnostics">Logging, events, and diagnostics</see> for more information and examples.
/// </para>
/// </remarks>
/// <param name="source">The query source.</param>
/// <returns>The query string for debugging.</returns>
public static DbCommand CreateDbCommand(this IQueryable source)
=> source.Provider.Execute<IEnumerable>(source.Expression) is IRelationalQueryingEnumerable queryingEnumerable
? queryingEnumerable.CreateDbCommand()
: throw new NotSupportedException(RelationalStrings.NoDbCommand);
#region FromSql
/// <summary>
/// Creates a LINQ query based on a raw SQL query.
/// </summary>
/// <remarks>
/// <para>
/// If the database provider supports composing on the supplied SQL, you can compose on top of the raw SQL query using
/// LINQ operators: <c>context.Blogs.FromSqlRaw("SELECT * FROM Blogs").OrderBy(b => b.Name)</c>.
/// </para>
/// <para>
/// As with any API that accepts SQL it is important to parameterize any user input to protect against a SQL injection
/// attack. You can include parameter place holders in the SQL query string and then supply parameter values as additional
/// arguments. Any parameter values you supply will automatically be converted to a <see cref="DbParameter" />.
/// </para>
/// <para>
/// However, <b>never</b> pass a concatenated or interpolated string (<c>$""</c>) with non-validated user-provided valuesView on GitHub (pinned to 3a2006ef56)