SEO keywords: EF Core performance, Entity Framework Core optimization, SQL Server .NET, MySQL .NET, PostgreSQL .NET, Web API performance.
Entity Framework Core is powerful, but performance problems appear quickly when queries load too much data, skip indexes, or track objects unnecessarily. Whether you use SQL Server, MySQL, or PostgreSQL, the same core habits can make your .NET application faster and more reliable.
Use Projections Instead of Loading Full Entities
If your API only needs a few fields, select only those fields. This reduces memory usage, network transfer, and database work.
var products = await db.Products
.Where(x => x.IsActive)
.Select(x => new ProductListItem
{
Id = x.Id,
Name = x.Name,
Price = x.Price
})
.ToListAsync(cancellationToken);
Use AsNoTracking for Read-Only Queries
Tracking is useful when you plan to update entities. For read-only API responses, no-tracking queries are usually faster.
var orders = await db.Orders
.AsNoTracking()
.Where(x => x.CustomerId == customerId)
.OrderByDescending(x => x.CreatedAt)
.Take(20)
.ToListAsync(cancellationToken);
Always Paginate Large Results
Never return unlimited rows from a Web API endpoint. Use pagination and put a maximum page size in place.
var pageSize = Math.Min(request.PageSize, 50);
var page = Math.Max(request.Page, 1);
var items = await db.Articles
.AsNoTracking()
.OrderByDescending(x => x.PublishedAt)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync(cancellationToken);
Add the Right Indexes
EF Core cannot save a query that has no proper database index. Add indexes for columns used in filtering, sorting, and joins.
modelBuilder.Entity<Article>()
.HasIndex(x => new { x.Status, x.PublishedAt });
modelBuilder.Entity<Order>()
.HasIndex(x => x.CustomerId);
Database-Specific Notes
- SQL Server: review execution plans and avoid unnecessary includes.
- MySQL: check collation and index length for string-heavy queries.
- PostgreSQL: use indexes carefully for JSONB, full-text search, and case-insensitive queries.
Avoid N+1 Queries
N+1 happens when your code makes one query for a list and then one extra query for each item. Use projections or explicit includes when needed.
var orders = await db.Orders
.AsNoTracking()
.Where(x => x.CustomerId == customerId)
.Select(x => new OrderDto
{
Id = x.Id,
Total = x.Total,
Items = x.Items.Select(i => new OrderItemDto
{
ProductName = i.Product.Name,
Quantity = i.Quantity
}).ToList()
})
.ToListAsync(cancellationToken);
Final Thoughts
EF Core performance is mostly about discipline: select less data, track only when needed, paginate everything, index correctly, and inspect SQL. These habits work across SQL Server, MySQL, and PostgreSQL and make your .NET Web APIs much more production-ready.