When working with Entity Framework (EF), developers often face challenges in optimizing database performance, especially when dealing with complex business logic and large datasets. One effective way to improve performance is by leveraging stored procedures, which are pre-compiled SQL code that runs on the server-side.

Why Use Stored Procedures?
Stored procedures are a powerful tool in the database administrator’s (DBA) arsenal. They offer several benefits, including:
1. Complex business logic: Stored procedures allow DBAs to encapsulate complex business logic in SQL code, making it easier to maintain and update.
2. Performance-critical queries: By using stored procedures, you can take advantage of a fixed execution plan, which can lead to significant performance improvements.
3. Security: Stored procedures restrict direct table access, reducing the risk of SQL injection attacks and other security vulnerabilities.
4. Legacy system integration: If you’re working with a legacy system that already has existing stored procedures, using them can simplify the integration process.
Calling Stored Procedures in EF Core
EF Core provides several ways to call stored procedures, each with its own strengths and weaknesses. In this section, we will explore three methods: FromSqlRaw, SqlQueryRaw, and ExecuteSqlRawAsync.
Method 1: FromSqlRaw
FromSqlRaw is used when the stored procedure returns rows that map to an entity. This method is similar to using the DbSet interface, but it allows you to execute a raw SQL query directly.
Example:
var orders = await dbContext.Orders.FromSqlRaw("EXEC GetOrdersByCustomer @CustomerId = {0}", customerId).ToListAsync();
When using FromSqlRaw, make sure to specify the parameter values explicitly using SqlParameter objects.
Example:
var param = new SqlParameter("@CustomerId", customerId); var orders = await dbContext.Orders.FromSqlRaw("EXEC GetOrdersByCustomer @CustomerId", param).ToListAsync();
Method 2: SqlQueryRaw
SqlQueryRaw is used when the stored procedure returns columns that don’t map to an existing entity. This method returns a raw SQL query result, which can be mapped to a custom DTO (Data Transfer Object).
Example:
var summaries = await dbContext.Database.SqlQueryRaw("EXEC GetOrderSummaries @From, @To", new SqlParameter("@From", fromDate), new SqlParameter("@To", toDate)).ToListAsync();
Method 3: ExecuteSqlRawAsync
ExecuteSqlRawAsync is used for stored procedures that don’t return any rows, such as INSERT, UPDATE, or DELETE procedures.
Example:
await dbContext.Database.ExecuteSqlRawAsync("EXEC ArchiveOldOrders @CutoffDate", new SqlParameter("@CutoffDate", cutoffDate));
Output Parameters
Output parameters are used to return values from a stored procedure. To use output parameters with EF Core, you need to specify the ParameterDirection.Output property when creating the SqlParameter object.
Example:
var orderIdParam = new SqlParameter { ParameterName = "@OrderId", SqlDbType = SqlDbType.UniqueIdentifier, Direction = ParameterDirection.Output }; var statusParam = new SqlParameter { ParameterName = "@Status", SqlDbType = SqlDbType.NVarChar, Size = 50, Direction = ParameterDirection.Output }; await dbContext.Database.ExecuteSqlRawAsync("EXEC CreateOrder @CustomerId, @Product, @OrderId OUTPUT, @Status OUTPUT", new SqlParameter("@CustomerId", customerId), new SqlParameter("@Product", product), orderIdParam, statusParam); var newOrderId = (Guid)orderIdParam.Value; var status = (string)statusParam.Value;
ORM Comparison
When choosing an Object-Relational Mapping (ORM) tool, it’s essential to consider the trade-offs between different options. In this section, we will compare EF Core, Dapper, and NHibernate.
Entity Framework Core
EF Core is the default ORM for.NET and provides a full-featured set of tools for interacting with databases. It abstracts SQL for most operations, making it a great choice for CRUD (Create, Read, Update, Delete) operations.
Example:
var orders = await db.Orders.Where(o => o.CustomerId == id && o.Status == OrderStatus.Active).Include(o => o.Lines).OrderByDescending(o => o.CreatedAt).Take(50).AsNoTracking().ToListAsync();
Dapper
Dapper is a micro-ORM developed by the Stack Overflow team. It maps raw SQL results to objects, making it a great choice for maximum performance and fine-grained SQL control.
Example:
using var connection = new SqlConnection(connectionString); var orders = await connection.QueryAsync("SELECT * FROM Orders WHERE CustomerId = @CustomerId AND Status = @Status", new { CustomerId = id, Status = "Active" });
NHibernate
NHibernate is a mature, feature-rich ORM with a long history. It provides a high level of abstraction and flexibility, making it a great choice for complex business logic and legacy system integration.
Example:
var orders = session.Query().Where(o => o.CustomerId == id && o.Status == OrderStatus.Active).ToList();
Best Practices for Calling Stored Procedures
When calling stored procedures with EF Core, follow these best practices to ensure optimal performance and security:
1. Use parameterized queries to prevent SQL injection attacks.
2. Specify the ParameterDirection.Output property when using output parameters.
3. Use the FromSqlRaw method for stored procedures that return rows that map to an entity.
4. Use the SqlQueryRaw method for stored procedures that return columns that don’t map to an existing entity.
5. Use the ExecuteSqlRawAsync method for stored procedures that don’t return any rows.
Conclusion
Calling stored procedures with Entity Framework optimization is a powerful technique for improving database performance and security. By following the strategies outlined in this article, you can streamline your database interactions and improve the overall efficiency of your application. Remember to use parameterized queries, specify the ParameterDirection.Output property, and choose the right ORM tool for your scenario.
Additional Tips and Considerations
When working with stored procedures, consider the following additional tips and considerations:
You may also enjoy reading: 11 Essential Markdown Tricks to Supercharge Your Astro Site.
1. Use stored procedures for complex business logic and performance-critical queries.
2. Restrict direct table access using stored procedures.
3. Integrate existing stored procedures from legacy systems.
4. Use output parameters to return values from stored procedures.
5. Choose the right ORM tool based on your specific needs.
By following these tips and considering the best practices outlined in this article, you can take your database interactions to the next level and improve the overall performance and security of your application.
Final Thoughts
Calling stored procedures with Entity Framework optimization is a powerful technique that can help improve database performance and security. By following the strategies outlined in this article, you can streamline your database interactions and improve the overall efficiency of your application. Remember to use parameterized queries, specify the ParameterDirection.Output property, and choose the right ORM tool for your scenario.
Common Mistakes to Avoid
When working with stored procedures, avoid the following common mistakes:
1. Not using parameterized queries, leading to SQL injection attacks.
2. Not specifying the ParameterDirection.Output property, leading to errors.
3. Using the wrong ORM tool for your scenario, leading to performance issues.
4. Not following best practices for stored procedure development, leading to maintenance issues.
By avoiding these common mistakes and following the best practices outlined in this article, you can ensure optimal performance and security when working with stored procedures and Entity Framework.
Real-World Examples
Here are some real-world examples of how stored procedures can be used with Entity Framework optimization:
Example 1:
Suppose you have a stored procedure that returns a list of orders for a given customer. You can use the FromSqlRaw method to call this stored procedure and retrieve the orders.
Example 2:
Suppose you have a stored procedure that inserts a new order into the database. You can use the ExecuteSqlRawAsync method to call this stored procedure and insert the new order.
Example 3:
Suppose you have a stored procedure that returns a list of products for a given category. You can use the SqlQueryRaw method to call this stored procedure and retrieve the products.
These real-world examples demonstrate how stored procedures can be used with Entity Framework optimization to improve database performance and security.
Future Development
As Entity Framework continues to evolve, we can expect to see new features and improvements that make it easier to work with stored procedures. Some potential future developments include:
1. Improved support for output parameters.
2. Enhanced performance for complex queries.
3. Better integration with other ORM tools.
By staying up-to-date with the latest developments in Entity Framework, you can ensure that your applications remain efficient and secure.





