EF Core can safely pass values to raw SQL queries by sending them as database parameters instead of inserting them directly into the SQL text.
Use parameterized APIs such as FromSql when the variable parts of a query are data values. Use a raw SQL API when part of the SQL structure itself must be constructed dynamically.
For the official EF Core guidance on raw SQL parameterization, see SQL Queries - Passing parameters.
Pass Parameters with FromSql
Use FromSql with interpolated values when a raw SQL query needs data parameters.
For example, the following query returns products whose price is at least the specified value:
var minimumPrice = 25m;
var products = await context.Products
.FromSql($"SELECT * FROM Products WHERE Price >= {minimumPrice}")
.ToListAsync();
Although minimumPrice appears inside an interpolated string, EF Core does not insert 25 directly into the SQL text.
FromSql accepts a FormattableString, which allows EF Core to receive the SQL format and the interpolated values separately. EF Core converts minimumPrice into a database parameter and sends its value separately from the SQL command.
Conceptually, the value follows this path:
minimumPrice
↓
interpolated value
↓
database parameter
↓
SQL command + parameter value
The exact parameter name generated by EF Core is an implementation detail and can vary. Conceptually, the command is similar to:
SELECT *
FROM Products
WHERE Price >= @p0
with 25 supplied separately as the value of @p0.
This means the database treats the parameter as a data value, rather than as part of the SQL command itself.
Use this pattern when the variable parts of the query are values such as:
- product IDs;
- names;
- prices;
- dates;
- Boolean values.
The database provider can then handle each parameter using the appropriate database representation without requiring the application to manually quote or escape the value.
Important: Database parameters represent data values. They cannot normally replace SQL structure such as table names, column names, operators, or SQL keywords. Later in this article,
FromSqlRawshows how to handle cases where part of the SQL structure itself must vary.
When automatic parameter creation is not enough, you can also supply an explicit DbParameter to control how a value is sent to the database.
For more about querying mapped entities, calling stored procedures, including related data, and composing LINQ over raw SQL, see FromSql in EF Core (Coming soon).
Pass a DbParameter
In most cases, you do not need to create a database parameter manually. When you pass an interpolated value to FromSql, EF Core creates the parameter for you.
Create a DbParameter explicitly when you need more control over the parameter sent to the database.
DbParameter is an ADO.NET abstraction, so you use the concrete parameter type provided by your database provider. For example, SQLite uses SqliteParameter.
DbParameter minimumPriceParameter = new SqliteParameter("@minimumPrice", 25m);
var products = await context.Products
.FromSql($"SELECT * FROM Products WHERE Price >= {minimumPriceParameter}")
.ToListAsync();
In this example, minimumPriceParameter is already a database parameter before it is passed to FromSql.
EF Core uses that parameter when building the database command, so its value remains separate from the SQL text.
The query still returns Product entities; using an explicit parameter changes how the value is supplied, not the shape of the result.
Creating the parameter explicitly can be useful when the application needs to control parameter details instead of relying entirely on provider inference.
Depending on the database provider, this can include details such as:
- the parameter name;
- database type;
- size;
- precision;
- scale.
Other relational providers use their own DbParameter implementations, such as SqlParameter for SQL Server.
Explicit parameters can also be useful when calling stored procedures whose parameter names, types, or other facets must match the procedure definition.
Creating the parameter manually changes who defines the parameter, not the basic parameterization model.
With normal FromSql interpolation, EF Core creates the parameter for you. With an explicit DbParameter, the application defines the parameter before EF Core builds the command.
Use an explicit DbParameter when you need additional control over the database parameter, not simply because a query contains a value.
Use FromSqlRaw When SQL Structure Must Vary
Database parameters are designed to represent data values. They cannot normally replace SQL structure such as table names, column names, operators, or SQL keywords.
For example, a value such as "Laptop" can be sent as a database parameter, but a column name such as Name must become part of the SQL text itself.
When part of the SQL structure must be constructed dynamically, use FromSqlRaw.
The following example chooses the column dynamically while still passing the comparison value as a parameter:
var columnName = "Name";
var columnValue = "Laptop";
var sql = $"SELECT * FROM Products WHERE {columnName} = {{0}}";
var products = await context.Products
.FromSqlRaw(sql, columnValue)
.ToListAsync();
The two variables are handled differently.
columnName becomes part of the SQL text because a column identifier cannot be represented by a database parameter.
The {0} placeholder is different. It is preserved in the SQL string passed to FromSqlRaw, and columnValue is supplied separately as an additional argument.
EF Core converts that argument into a database parameter, so "Laptop" remains separate from the SQL text.
Conceptually:
columnName
↓
inserted into SQL structure
columnValue
↓
passed separately
↓
database parameter
This distinction is important when working with dynamic SQL:
- SQL structure must be part of the SQL text;
- data values should still be passed as parameters.
Content inserted directly into the SQL text is not parameterized automatically. For that reason, dynamic identifiers such as column names should come from a trusted source or be validated before the query is executed.
FromSqlRaw is useful when SQL structure genuinely needs to vary. When only data values change, prefer FromSql, which parameterizes interpolated values automatically.
The query still returns Product entities; changing how the SQL is constructed does not change the result shape.
Validate Dynamic SQL Fragments
When part of the SQL structure is inserted directly into the SQL text, the application is responsible for making sure that fragment is safe.
This is different from passing a data value as a parameter.
For example, suppose an application allows the user to choose which product column should be searched:
var columnName = "Name";
Because a column name cannot normally be represented by a database parameter, columnName must become part of the SQL text.
Do not insert arbitrary input directly into that position.
Instead, restrict user-controlled choices to a known set of supported SQL identifiers:
var allowedColumns = new HashSet<string>
{
"Name",
"Price"
};
if (!allowedColumns.Contains(columnName))
{
throw new ArgumentException("Invalid column name.");
}
Once the identifier has been accepted, it can be used as part of the dynamic SQL while data values continue to be supplied separately as parameters.
This gives the two inputs different responsibilities:
columnNamebecomes part of the SQL structure and must come from a trusted or validated source;- a comparison value such as
"Laptop"should still be sent as a database parameter.
Keep dynamic SQL limited to the part that genuinely cannot be parameterized.
Parameterization Across Raw SQL APIs
The same distinction between parameterized values and dynamic SQL structure applies across the EF Core raw SQL API families.
| Operation | Parameterized API | Raw API |
|---|---|---|
| Query mapped entities | FromSql, FromSqlInterpolated |
FromSqlRaw |
| Query scalar or non-entity results | SqlQuery |
SqlQueryRaw |
| Execute SQL commands that do not return rows | ExecuteSql, ExecuteSqlInterpolated |
ExecuteSqlRaw |
For each family, use the parameterized API when the parts that vary are data values.
For example, interpolated values passed to SqlQuery are parameterized just as they are with FromSql. Use SqlQueryRaw when part of the SQL text itself must be constructed dynamically.
For scalar values, DTOs, and other non-entity raw SQL results, see SqlQuery in EF Core (Coming soon).
The same principle applies to ExecuteSql, ExecuteSqlAsync, ExecuteSqlInterpolated, and ExecuteSqlInterpolatedAsync: interpolated data values are parameterized. Use ExecuteSqlRaw or ExecuteSqlRawAsync when the command text itself must vary.
For executing SQL commands that do not return rows, see ExecuteSql in EF Core (Coming soon).
Across these API families, the rule remains the same:
- use parameters for data values;
- use a raw API when SQL structure genuinely needs to vary;
- keep any SQL fragment inserted directly into the command under application control or validate it before use.
Requirements and Important Notes
Parameterization is the preferred way to supply data values to raw SQL because the value is sent separately from the SQL text.
A few details are important when choosing how to supply those parameters.
Parameter Types Depend on the Database Provider
DbParameter defines the common ADO.NET abstraction for database parameters, but relational providers use their own concrete implementations.
For example:
- SQLite uses
SqliteParameter; - SQL Server uses
SqlParameter.
Provider-specific parameter types can expose or interpret details such as database types, sizes, precision, and scale differently.
When an application needs explicit control over those details, configure the parameter according to the requirements of the database provider being used.
Stored Procedure Parameters Must Match the Procedure Definition
When parameters are passed to a stored procedure, their names, types, and other required facets must match the procedure definition. When parameters are supplied positionally, their order must also match the procedure signature.
Named parameter notation can make calls with multiple or optional parameters easier to understand and can reduce the risk of supplying values in the wrong position.
For more about executing stored procedures that return mapped entities, see FromSql in EF Core (Coming soon).
Interpolated API Variants
FromSqlInterpolated also accepts an interpolated FormattableString and parameterizes interpolated data values.
FromSql was introduced in EF Core 7 and is the primary API used throughout this article.
For SQL commands that do not return rows, ExecuteSqlInterpolated and ExecuteSqlInterpolatedAsync are also valid interpolated variants and follow the same parameterization model.
Separate examples are not necessary here because these variants do not change the parameterization concept explained above.
Raw APIs Still Support Parameters
Using a raw API does not mean that every value must be inserted directly into the SQL string.
APIs such as FromSqlRaw, SqlQueryRaw, ExecuteSqlRaw, and their applicable asynchronous variants can still receive values separately as parameters.
Use the raw form for the portion of the command that genuinely needs dynamic SQL text, and continue passing data values as parameters whenever possible.
External Resources - Query Parameters
The following videos provide practical demonstrations of SQL parameterization and raw SQL in EF Core. They complement the examples in this article with visual walkthroughs of FormattableString, explicit database parameters, SQL injection risks, and the differences between parameterized and raw SQL APIs.
Video 1 - Everything You Need To Know About EF Core 8 Raw SQL Queries
This video by Milan Jovanović demonstrates how EF Core parameterizes interpolated values when using raw SQL APIs that accept a FormattableString, and contrasts that behavior with raw APIs that accept a regular SQL string.
Key timestamps:
- 01:46 — Explains how a
FormattableStringconverts an interpolated value into a SQL parameter and avoids SQL injection for that value. - 03:16 — Shows the executed SQL and confirms that the interpolated order ID was converted into the
P0SQL parameter. - 04:38 — Introduces
SqlQueryRawand explains the distinction between a raw SQL string and the parameterizedFormattableStringAPI. - 05:36 — Shows how a value can still be passed separately as a parameter when using a raw SQL API.
The video was recorded while EF Core 8 was still in preview, but the selected sections remain useful for understanding FormattableString, automatic parameterization, and the distinction between parameterized and raw SQL APIs.
Video 2 - Avoiding SQL Injection in Entity Framework Core (While using inline queries)
This video by DotNet Core Central demonstrates several SQL parameterization patterns in EF Core and contrasts parameterized values with SQL construction that can expose an application to SQL injection.
Key timestamps:
- 00:52 — Shows an explicit
SqlParameterbeing passed to a raw SQL command. - 01:42 — Shows a raw SQL overload receiving a value separately and explains that EF Core converts it into a database parameter.
- 02:07 — Contrasts a correctly parameterized value with a value inserted directly through string interpolation.
- 06:46 — Begins a practical SQL injection demonstration and shows how the parameterized version treats malicious input as data.
The video uses older EF Core raw SQL APIs, but its demonstrations of explicit parameters, separately supplied values, and SQL injection remain useful for understanding why data values should be parameterized.
Video 3 - Entity Framework Core 8 SQL Injection Attacks
This English-language video by Coding Tutorials provides a detailed demonstration of SQL parameterization in EF Core 8 and shows how explicit parameters and FormattableString keep data values separate from SQL text.
Key timestamps:
- 07:34 — Demonstrates a parameterized query using an explicit
SqliteParameterand supplies the value separately from the SQL text. - 12:02 — Introduces
FormattableStringand shows how it keeps the format and interpolated arguments separate. - 13:25 — Connects
FormattableStringdirectly toSqlQueryand explains how EF Core uses it to produce a parameterized query. - 14:45 — Contrasts
SqlQuerywithSqlQueryRawand shows why converting interpolated content into a regular SQL string changes the security model.
The video uses an EF Core 8 release candidate, but the selected sections remain directly relevant to explicit parameters, FormattableString, and the difference between parameterized and raw SQL APIs.
Video 4 - Raw SQL queries & stored procedures in Entity Framework Core
This video by Round The Code demonstrates practical raw SQL usage in EF Core 8 with SQL Server, including an explicit SqlParameter passed to FromSqlRaw and a separate example using FromSql.
Key timestamps:
- 01:55 — Starts the raw SQL example with
FromSqlRawand builds a query that filters products by an ID value. - 02:21 — Creates a
SqlParameterexplicitly and assigns its parameter name and value. - 02:36 — Executes the query with the separately supplied parameter and retrieves the matching result.
- 06:04 — Shows the
FromSqlAPI in a separate example and notes itsFormattableStringusage.
The strongest contribution of this video is its concise SQL Server example showing how an explicit provider-specific parameter is created and supplied separately to a raw SQL query.
Summary
EF Core raw SQL APIs support parameterization so that data values can be sent separately from the SQL command.
Key points:
- use
FromSqlwith interpolated data values to let EF Core create database parameters automatically; - use an explicit
DbParameterwhen you need additional control over details such as the parameter type, size, precision, or scale; - database parameters represent data values, not SQL structure such as table or column names;
- use
FromSqlRawwhen part of the SQL structure genuinely needs to be constructed dynamically; - keep dynamically inserted SQL fragments under application control or validate them before use;
- even when using raw APIs, continue passing data values separately as parameters;
- the same parameterized-versus-raw distinction applies to the
SqlQueryandExecuteSqlAPI families.
Related Articles
The following articles cover the raw SQL operations that use the parameterization patterns explained on this page:
- FromSql in EF Core (Coming soon) — Query mapped entity types using raw SQL, including stored procedures and LINQ composition.
- SqlQuery in EF Core (Coming soon) — Query scalar values and non-entity CLR types using raw SQL.
- ExecuteSql in EF Core (Coming soon) — Execute SQL commands that do not return rows.
- LINQ Queries in EF Core — Build and execute EF Core queries without writing raw SQL when the operation can be expressed with LINQ.
FAQ
Does FromSql protect against SQL injection?
FromSql parameterizes interpolated data values instead of inserting those values directly into the SQL text.
This protects those values from being interpreted as SQL syntax.
However, parameterization applies to data values. If an application dynamically constructs SQL structure, such as a column name, that fragment must come from a trusted source or be validated before it is inserted into the SQL.
What is the difference between FromSql and FromSqlRaw for parameters?
FromSql accepts an interpolated FormattableString, allowing EF Core to turn interpolated data values into database parameters automatically.
FromSqlRaw accepts raw SQL text and is useful when part of the SQL structure itself must be constructed dynamically.
Values passed separately to FromSqlRaw can still be sent as database parameters.
When should I create a DbParameter manually?
Create a DbParameter explicitly when you need control over how the parameter is defined, such as its name, database type, size, precision, or scale.
For ordinary data values, normal FromSql interpolation is usually sufficient because EF Core creates the parameter automatically.
Can I use a parameter for a table or column name?
Normally, no.
Database parameters represent data values. SQL identifiers such as table names and column names are part of the SQL structure and must appear in the command text itself.
If those identifiers need to vary dynamically, restrict them to trusted or validated choices and use an appropriate raw SQL API.
Is FromSqlRaw unsafe?
FromSqlRaw is not inherently unsafe.
The risk appears when untrusted content is inserted directly into the SQL text. Dynamic SQL fragments should be controlled or validated, while data values should continue to be supplied separately as parameters.
Do SqlQuery and ExecuteSql parameterize interpolated values too?
Yes.
SqlQuery, ExecuteSql, and ExecuteSqlAsync follow the same general parameterization pattern as FromSql: interpolated data values are converted into database parameters.
Their corresponding raw variants are available when part of the SQL text itself must be constructed dynamically.