C#

Raw SQL Query without DbSet - Entity Framework Core

19 September 2026 · 10 min read

Raw SQL Query without DbSet - Entity Framework Core

Entity Framework Core (EF Core) is a powerful Object-Relational Mapper (ORM) that simplifies database interactions in .NET applications. While EF Core excels at abstracting database operations through DbSets and LINQ queries, there are times when you need the fine-grained control and performance optimization that only raw SQL queries can provide. This is especially true when dealing with complex queries, stored procedures, or legacy database schemas. Using raw SQL query without DbSet provides the flexibility to directly interact with the database, bypassing the ORM layer for specific operations. This approach offers advantages in terms of performance tuning and accessing database-specific features not directly exposed by EF Core’s standard querying mechanisms. It’s a technique that empowers developers to leverage the full potential of their chosen database system within the context of an EF Core application. This article will explore how to execute raw SQL queries in EF Core without relying on DbSets, offering practical examples and best practices.

Why Use Raw SQL Queries in EF Core?

While EF Core offers a robust set of tools for querying and manipulating data, there are scenarios where resorting to raw SQL queries becomes necessary and even advantageous. One primary reason is performance. Complex LINQ queries can sometimes generate inefficient SQL, leading to slow execution times. Writing a hand-optimized raw SQL query allows you to directly control the query plan and potentially achieve significant performance gains. Another compelling reason is accessing database-specific features. Different database systems offer unique functions, stored procedures, and extensions that might not be directly supported by EF Core’s abstraction layer. In these cases, raw SQL queries provide a way to leverage these features directly. For example, you might want to use PostgreSQL’s JSON functions or SQL Server’s windowing functions. Finally, integrating with legacy databases or systems can be simplified by using raw SQL queries. These systems may have complex schemas or stored procedures that are difficult to map to EF Core entities.

Consider a situation where you need to execute a complex stored procedure for generating a report. This stored procedure might involve intricate calculations and data aggregations that are difficult to express using LINQ. Executing it directly with a raw SQL query can be a more straightforward and efficient approach. According to Microsoft’s documentation, using FromSqlRaw or SqlQuery can sometimes lead to significant performance improvements compared to generated SQL. Microsoft EF Core Documentation.

Here are some key benefits of using raw SQL queries:

  • Performance Optimization: Fine-tune queries for maximum speed.
  • Access to Database-Specific Features: Utilize unique functions and procedures.
  • Integration with Legacy Systems: Work seamlessly with existing database structures.

Executing Raw SQL Queries Without DbSet

EF Core provides several ways to execute raw SQL queries without directly using DbSets. One common approach is using the Database.SqlQuery<T>() method (in older versions of EF Core) or Database.SqlQueryRaw<T>() or Database.SqlQueryRaw<T>() method (in newer versions of EF Core). This method allows you to execute a raw SQL query and map the results directly to a .NET type. This is particularly useful when the query returns data that doesn’t directly correspond to an existing entity in your EF Core model. Another method involves using Database.ExecuteSqlRaw() or Database.ExecuteSqlInterpolated() to execute non-query SQL commands like INSERT, UPDATE, or DELETE statements. These methods are ideal for performing data modifications directly without retrieving data into entities.

For example, suppose you want to retrieve a list of customer names and order counts from a database, but you don’t have a corresponding entity for this specific data structure. You can use SqlQueryRaw to execute a raw SQL query that returns this data and map it to a custom class or struct. This approach allows you to bypass the DbSet mapping entirely and work directly with the query results. The key is to define a class or struct that matches the columns returned by your SQL query. This allows EF Core to properly map the data. Keep in mind that the column names in your SQL query must match the property names in your class or struct for the mapping to work correctly.

Here’s a featured snippet-optimized paragraph: To execute a raw SQL query without DbSet in EF Core, use the Database.SqlQueryRaw() method. This allows you to bypass the ORM layer and directly interact with the database. Define a class or struct that matches the columns returned by the SQL query, ensuring that column names in the SQL query match the property names in your class or struct for proper data mapping. This enables you to retrieve data and map it to a .NET type directly without relying on existing entities in your EF Core model.

Example: Retrieving Data with SqlQueryRaw

Here’s an example demonstrating how to use SqlQueryRaw to retrieve data:

  1. Define a class to hold the query results: ``` public class CustomerOrderCount { public string CustomerName { get; set; } public int OrderCount { get; set; } }
  2. Execute the raw SQL query: ``` var customerOrderCounts = context.Database.SqlQueryRaw(“SELECT CustomerName, COUNT() AS OrderCount FROM Orders GROUP BY CustomerName”);
  3. Iterate through the results: ``` foreach (var item in customerOrderCounts) { Console.WriteLine($“Customer: {item.CustomerName}, Order Count: {item.OrderCount}”); }

Parameterization and Security

When working with raw SQL queries, it’s crucial to prioritize security and prevent SQL injection vulnerabilities. SQL injection occurs when malicious users inject arbitrary SQL code into your queries through user input, potentially allowing them to access or modify sensitive data. To mitigate this risk, always use parameterized queries when incorporating user-provided values into your raw SQL queries. Parameterized queries allow the database to treat user input as data rather than executable code, effectively neutralizing SQL injection attempts.

EF Core provides mechanisms for parameterizing raw SQL queries through the @ symbol or by using interpolated strings with Database.ExecuteSqlInterpolated(). When using SqlQueryRaw, you can pass parameters as arguments to the method. When using ExecuteSqlInterpolated, EF Core automatically handles parameterization, making it a safer alternative compared to concatenating strings directly. Proper parameterization not only enhances security but also improves query performance. The database can cache and reuse query plans more efficiently when the query structure remains consistent, even with varying parameter values. Remember, security should be a top priority when dealing with raw SQL queries, and parameterization is a fundamental technique for safeguarding your application against SQL injection attacks.

Here’s how to use parameters with SqlQueryRaw:

var customerName = "John Doe"; var customerOrderCounts = context.Database.SqlQueryRaw<CustomerOrderCount>("SELECT CustomerName, COUNT() AS OrderCount FROM Orders WHERE CustomerName = {0} GROUP BY CustomerName", customerName); 

Or, with ExecuteSqlInterpolated:

var customerName = "John Doe"; var rowsAffected = context.Database.ExecuteSqlInterpolated($"UPDATE Customers SET IsActive = false WHERE CustomerName = {customerName}"); 

When to Avoid Raw SQL Queries

While raw SQL queries offer flexibility and control, they should not be the default approach for all database interactions in EF Core. Overusing raw SQL queries can diminish the benefits of using an ORM, such as code maintainability, type safety, and database abstraction. It’s essential to carefully consider the trade-offs before resorting to raw SQL queries. If a query can be efficiently expressed using LINQ and EF Core’s standard querying mechanisms, it’s generally preferable to do so. LINQ queries are typically more readable, maintainable, and less prone to errors compared to hand-written SQL. Furthermore, EF Core’s query translation engine can often optimize LINQ queries for performance, making them surprisingly efficient.

You should primarily use raw SQL queries when you need to optimize performance, access database-specific features, or integrate with legacy systems that are difficult to map to EF Core entities. For simple CRUD operations or queries that can be easily expressed in LINQ, stick with EF Core’s standard querying methods. Always strive to maintain a balance between leveraging the power of raw SQL queries and adhering to the principles of ORM to ensure code quality and maintainability. Remember to thoroughly test your raw SQL queries to ensure they function as expected and don’t introduce any unexpected side effects.

Key scenarios where you might not need raw SQL queries:

  • Simple CRUD operations on entities.
  • Queries that can be easily expressed with LINQ.
  • When code maintainability and readability are paramount.
Infographic here
FAQ ---
What are the advantages of using raw SQL queries?
Raw SQL queries offer fine-grained control over database interactions, enabling performance optimization, access to database-specific features, and integration with legacy systems.
How can I prevent SQL injection when using raw SQL queries?
Always use parameterized queries to treat user input as data rather than executable code, preventing malicious SQL injection attempts.
When should I avoid using raw SQL queries?
Avoid raw SQL queries for simple CRUD operations or queries that can be efficiently expressed using LINQ and EF Core's standard querying mechanisms.
What is the difference between SqlQueryRaw and ExecuteSqlRaw?
SqlQueryRaw is used to execute queries that return data, while ExecuteSqlRaw is used to execute non-query commands like INSERT, UPDATE, or DELETE statements.
Mastering **raw SQL query without DbSet** in Entity Framework Core unlocks a new level of control and optimization for your database interactions. By understanding when and how to use **raw SQL queries** effectively, you can overcome limitations of ORMs and harness the full power of your chosen database system. From performance tuning to accessing database-specific features, the ability to execute **raw SQL queries** empowers you to build robust and efficient applications. Remember to prioritize security by always using parameterized queries to prevent SQL injection vulnerabilities. As you continue your journey with EF Core, consider exploring advanced techniques like executing stored procedures and using database functions directly within your **raw SQL queries**. This knowledge will enable you to tackle even the most complex database challenges with confidence. To further enhance your knowledge, explore the official Microsoft documentation and related articles on advanced EF Core techniques. [Entity Framework Core Raw SQL Query Tutorial](https://www.entityframeworktutorial.net/efcore/raw-sql-query-in-ef-core.aspx), [Microsoft EF Core Learning](https://learn.microsoft.com/en-us/ef/core/) and [our other EF Core articles](https://courthousezoological.com/n7sqp6kh?key=e6dd02bc5dbf461b97a9da08df84d31c) for a deeper dive.

Question & Answer :
With Entity Framework Core removing dbData.Database.SqlQuery<SomeModel> I can’t find a solution to build a raw SQL Query for my full-text search query that will return the tables data and also the rank.

The only method I’ve seen to build a raw SQL query in Entity Framework Core is via dbData.Product.FromSql("SQL SCRIPT"); which isn’t useful as I have no DbSet that will map the rank I return in the query.

Any Ideas???

EF Core 8 and newer

The SqlQuery method was added in EF Core 7.0 to support returning scalar values.

Starting from EF Core 8, this method will additionally support returning arbitrary types.


EF Core 3.0

You need to use keyless entity types, previously known as query types:

This feature was added in EF Core 2.1 under the name of query types. In EF Core 3.0 the concept was renamed to keyless entity types. The [Keyless] Data Annotation became available in EFCore 5.0.

To use them you need to first mark your class SomeModel with [Keyless] data annotation or through fluent configuration with .HasNoKey() method call like below:

public DbSet<SomeModel> SomeModels { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<SomeModel>().HasNoKey(); } 

After that configuration, you can use one of the methods explained here to execute your SQL query. For example you can use this one:

var result = context.SomeModels.FromSqlRaw("SQL SCRIPT").ToList(); var result = await context.SomeModels.FromSql("SQL_SCRIPT").ToListAsync(); 

EF Core 2.1

If you’re using EF Core 2.1 Release Candidate 1 available since 7 may 2018, you can take advantage of the proposed new feature which is query types:

In addition to entity types, an EF Core model can contain query types, which can be used to carry out database queries against data that isn’t mapped to entity types.

When to use query type?

Serving as the return type for ad hoc FromSql() queries.

Mapping to database views.

Mapping to tables that do not have a primary key defined.

Mapping to queries defined in the model.

So you no longer need to do all the hacks or workarounds proposed as answers to your question. Just follow these steps:

First you defined a new property of type DbQuery<T> where T is the type of the class that will carry the column values of your SQL query. So in your DbContext you’ll have this:

public DbQuery<SomeModel> SomeModels { get; set; } 

Secondly use FromSql method like you do with DbSet<T>:

var result = context.SomeModels.FromSql("SQL_SCRIPT").ToList(); var result = await context.SomeModels.FromSql("SQL_SCRIPT").ToListAsync(); 

Also note that DbContexts are partial classes, so you can create one or more separate files to organize your ‘raw SQL DbQuery’ definitions as best suits you.