For years, the "IRM vs. Stored Procedures" debate divided .NET developers. In 2026, with the release of Entity Framework Core 10 (EF10), the war is over. The answer is "Both." EF10 creates a seamless bridge, allowing developers to enjoy the productivity of an ORM with the raw power of pre-compiled database logic.
At Boundev, we architect high-throughput fintech and healthcare systems. Here is how we leverage stored procedures in modern .NET ecosystems.
Why Stored Procedures in 2026?
Performance
Query plans are cached on the server. For complex joins across 10+ tables or heavy aggregation, SQL Server optimizes better than LINQ translation.
Security
Granular permissions. You can grant execution rights on a procedure without giving direct SELECT/UPDATE access to the underlying tables.
1. Reading Data: FromSqlRaw Done Right
The FromSqlRaw method is your gateway. However, it is a double-edged sword. Writing it incorrectly invites SQL Injection.
// ❌ DANGEROUS: Do NOT do this
var data = ctx.Users.FromSqlRaw("EXEC GetUser " + userId).ToList();
<p class="text-gray-500 mb-2">// ✅ SAFE: EF Core parameterizes this automatically</p>
<p class="text-green-700 font-bold">
var data = ctx.Users.FromSqlRaw("EXEC GetUser {0}", userId).ToList();
</p>
Mapping to Non-Entity Types
Historically, EF required a DbSet for everything. In EF Core 10, mapping arbitrary SQL results to simpler DTOs (Data Transfer Objects) is trivial with Database.SqlQuery<T>.
// EF Core 10 Style
var report = await _context.Database
.SqlQuery<MonthlySalesDto>($"EXEC GetSales {startDate}, {endDate}")
.ToListAsync();
2. Writing Data: CUD Operations
For high-volume inserts or updates, LINQ's tracking overhead can be heavy. Use stored procedures for batch operations.
In 2026, ExecuteSqlRawAsync is the standard for non-query commands.
// Async execution returning rows affected
int rowsAffected = await _context.Database
.ExecuteSqlRawAsync("EXEC UpdateInventory @p0, @p1", productId, newStockLevel);
if (rowsAffected == 0) throw new Exception("Update failed");
3. Output Parameters in 2026
Handling OUTPUT parameters used to be clumsy. Now, utilizing Microsoft.Data.SqlClient alongside EF Core is clean and typesafe.
Step 1: Define Parameter
var outParam = new SqlParameter
Create a standard SQL parameter object and set its direction to Output. Be sure to define the correct Size for strings.
Step 2: Execute & Read
outParam.Value
After ExecuteSqlRawAsync completes, the value is populated immediately. You don't need to open a separate connection.
Comparison: LINQ vs. Stored Procedures
| Feature | LINQ (EF Core) | Stored Procedure |
|---|---|---|
| maintainability | High (In code) | Medium (In DB) |
| Performance | Good (optimized in EF10) | Best (Pre-compiled) |
| Network Traffic | Higher (sends logic) | Minimal (sends call) |
| Debugging | Easy (Visual Studio) | Harder (SSMS) |
Frequently Asked Questions
Does EF Core 10 support stored procedures returning multiple result sets?
Yes, but it still requires dropping down to underlying ADO.NET or using third-party extensions. EF Core natively focuses on mapping a single result set to minimal code complexity.
<div itemscope itemprop="mainEntity" itemtype="https://schema.org/Question" class="bg-white rounded-xl p-5 shadow-sm border border-gray-200">
<h3 itemprop="name" class="font-bold text-gray-900 mb-2">Can I perform migrations on stored procedures?</h3>
<div itemscope itemprop="acceptedAnswer" itemtype="https://schema.org/Answer">
<p itemprop="text" class="text-gray-600">Yes. You can include raw SQL in your <code>Up()</code> and <code>Down()</code> migration methods using <code>migrationBuilder.Sql(...)</code> to create or alter procedures as part of your deployment pipeline.</p>
</div>
</div>
<div itemscope itemprop="mainEntity" itemtype="https://schema.org/Question" class="bg-white rounded-xl p-5 shadow-sm border border-gray-200">
<h3 itemprop="name" class="font-bold text-gray-900 mb-2">When should I use vector search in a stored procedure?</h3>
<div itemscope itemprop="acceptedAnswer" itemtype="https://schema.org/Answer">
<p itemprop="text" class="text-gray-600">If you are building AI features like "Find similar products" in 2026, delegate the cosine similarity calculation to SQL Server 2025 via a stored procedure. It's significantly faster than fetching embeddings to C#.</p>
</div>
</div>
<div itemscope itemprop="mainEntity" itemtype="https://schema.org/Question" class="bg-white rounded-xl p-5 shadow-sm border border-gray-200">
<h3 itemprop="name" class="font-bold text-gray-900 mb-2">Is FromSqlRaw safe?</h3>
<div itemscope itemprop="acceptedAnswer" itemtype="https://schema.org/Answer">
<p itemprop="text" class="text-gray-600">Only if you use parameter placeholders (e.g., <code>{0}</code> or <code>@p0</code>). Never use string concatenation (<code>"EXEC " + var</code>), as this opens your application to catastrophic SQL injection attacks.</p>
</div>
</div>
Optimize Your .NET Infrastructure
Scalability problems often hide in the database layer. Boundev's .NET experts can audit your EF Core implementation and boost performance by 50% or more.
Audit My Codebase