← Back to list

7 Secrets to Supercharging EF Core in .NET 8 — Why Your “Simple Setup” Might Be Slowing You Down

What’s the story?  You’ve probably wired up Entity Framework Core a dozen times by now. AddDbContext, connection string, SQL Server, done…

Michael Maurice · 2025-04-19 18:01 · 34 claps · 3.2 min read paywalled
#dotnet #entity-framework-core #clean-code #option-pattern #c-sharp-programming
Open on Medium ↗
Wiki topics: 💻 · Programming 🧘 · Spirituality

7 Secrets to Supercharging EF Core in .NET 8 — Why Your “Simple Setup” Might Be Slowing You Down

What’s the story? You’ve probably wired up Entity Framework Core a dozen times by now. AddDbContext, connection string, SQL Server, done and dusted. It works, sure—but what if I told you this “simple setup” might be quietly draining your app’s performance, limiting flexibility, and making future changes a nightmare?

If you’ve ever hardcoded a timeout or silently ignored retry settings because “the defaults seem fine,” then buckle up. This isn’t just about writing EF Core code that works — this is about writing EF Core code that wins. 💪

In this guide, we’ll not only level up your EF Core setup using .NET 8, but we’ll also sprinkle in some real-world performance boosts, killer maintainability tricks, and a dash of production-ready swagger.

🚀 1. If You Think AddDbContext Is Enough, It’s Not.

Yes, it gets EF Core up and running. But by default, it tracks every object you query — even if you’re just reading data. That’s like hiring a security guard to follow you while you browse the grocery store.

Instead, in read-only endpoints, use this:

var company = await dbContext.Companies
    .AsNoTracking()
    .FirstOrDefaultAsync(c => c.Id == id);

Why it matters: AsNoTracking() can improve read performance by up to 30%, especially when dealing with large datasets.

🕵️‍♂️ 2. Imagine That Your App Crashes Randomly… But Only Sometimes.

Welcome to the world of transient faults — temporary hiccups in your database connection that can ruin a user’s day (and your weekend).

Here’s how we fix that with retries and timeout settings:

options.UseSqlServer(connectionString, sqlOptions =>
{
    sqlOptions.EnableRetryOnFailure(
        maxRetryCount: 3,
        maxRetryDelay: TimeSpan.FromSeconds(5),
        errorNumbersToAdd: null
    );
    sqlOptions.CommandTimeout(30); // seconds
});

Key numbers to remember:

  • 🌀 MaxRetryCount = 3: Enough to handle blips, without going into infinite loop territory.
  • Timeout = 30s: Gives your long-running queries a fighting chance.

🧨 3. Do You Know What Happens If You Enable Sensitive Data Logging in Production?

It’s like broadcasting your passwords on a Times Square billboard. Don’t.

Still, in development, it’s incredibly helpful:

options.EnableSensitiveDataLogging();
options.EnableDetailedErrors();

Just make sure it’s wrapped in something like:

if (env.IsDevelopment())
{
    options.EnableSensitiveDataLogging();
}

📦 4. If You’re Hardcoding Settings, You’re Doing It Wrong

Hardcoded config = redeploy every time you want to tweak something.

Enter: appsettings.json

"DatabaseOptions": {
  "CommandTimeout": 30,
  "MaxRetryCount": 3
}

Then create a POCO:

public class DatabaseOptions
{
    public int CommandTimeout { get; set; }
    public int MaxRetryCount { get; set; }
}

🧩 5. The Options Pattern: The Best Thing You’re Not Using

This is where things get spicy. Instead of binding settings manually, use the Options pattern like a boss:

builder.Services.Configure<DatabaseOptions>(
    builder.Configuration.GetSection("DatabaseOptions"));

Inject it like so:

public class MyDbContext : DbContext
{
    private readonly DatabaseOptions _dbOptions;
public MyDbContext(DbContextOptions<MyDbContext> options, IOptions<DatabaseOptions> dbOptions)
        : base(options)
    {
        _dbOptions = dbOptions.Value;
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("YourConnectionString", sqlOptions =>
        {
            sqlOptions.CommandTimeout(_dbOptions.CommandTimeout);
            sqlOptions.EnableRetryOnFailure(_dbOptions.MaxRetryCount);
        });
    }
}

This way, a config change + app restart = new behavior. No code change, no redeploy. 🎉

🧪 6. Want to Know If It All Works? Here’s How to Test It

  • Set breakpoints inside OnConfiguring
  • Hit your endpoint from Postman
  • Check if values are picked from appsettings.json

Simple, visual, foolproof.

✅ 7. A Full .NET 8 Example for the Pros in the Room

Let’s tie everything together with a full Program.cs sample:

var builder = WebApplication.CreateBuilder(args);
// Bind config
builder.Services.Configure<DatabaseOptions>(
    builder.Configuration.GetSection("DatabaseOptions"));
// Register DbContext
builder.Services.AddDbContext<MyDbContext>((serviceProvider, options) =>
{
    var env = serviceProvider.GetRequiredService<IHostEnvironment>();
    var dbOptions = serviceProvider
        .GetRequiredService<IOptions<DatabaseOptions>>().Value;
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection"),
        sqlOptions =>
        {
            sqlOptions.CommandTimeout(dbOptions.CommandTimeout);
            sqlOptions.EnableRetryOnFailure(dbOptions.MaxRetryCount);
        });
    if (env.IsDevelopment())
    {
        options.EnableDetailedErrors();
        options.EnableSensitiveDataLogging();
    }
});
builder.Services.AddEndpointsApiExplorer();
var app = builder.Build();
app.MapGet("/company/{id}", async (int id, MyDbContext db) =>
{
    var company = await db.Companies
        .AsNoTracking()
        .FirstOrDefaultAsync(c => c.Id == id);
    return company is null
        ? Results.NotFound()
        : Results.Ok(new { company.Id, company.Name });
});
app.Run();

🎯 TL;DR — The Cheat Sheet

FeatureWhy It MattersAsNoTracking()Boosts read performanceRetry + Timeout SettingsHandles transient failuresSensitive Data LoggingDebugging tool—dev only!Options PatternDynamic config, no redeploysappsettings.jsonCentral, clean config sourceDependency InjectionRuntime-resolved, testable setup

🎉 Final Thoughts

If you’re still configuring EF Core the old way, you’re not just missing out — you’re potentially setting your app up for pain later. With just a little extra effort, you get faster queries, more flexible deployments, and rock-solid reliability.

So the next time you reach for AddDbContext, ask yourself:

“Am I building this for today — or for scale?”

And if you’re interested in building scalable, maintainable, and production-proof .NET apps, you should absolutely read this guide again — and share it with your team.

Because coding smart isn’t just about making it work. It’s about making it work well. 😎

Want more EF Core goodness? Drop a comment, share your setup, or ask me how to test migrations like a pro. Let’s geek out.


메타데이터
post_id
47d9e168fa5e
slug
7-secrets-to-supercharging-ef-core-in-net-8-why-your-simple-setup-might-be-slowing-you-down-47d9e168fa5e
url
https://medium.com/@michaelmaurice410/7-secrets-to-supercharging-ef-core-in-net-8-why-your-simple-setup-might-be-slowing-you-down-47d9e168fa5e
canonical_url
https://medium.com/@michaelmaurice410/7-secrets-to-supercharging-ef-core-in-net-8-why-your-simple-setup-might-be-slowing-you-down-47d9e168fa5e
author_url
https://medium.com/@michaelmaurice410
status
ok
fetched_at
2026-06-09 15:37:30