1. Choose the Right Query Execution Strategy
Use AsNoTracking() for Read-Only Queries
Use .AsNoTracking() when you are only reading data:
var users = context.Users.AsNoTracking().ToList();
This makes the query faster and uses less memory, which is great for applications that mostly read data.
Avoid Fetching Unnecessary Data
If you only need a few columns from a table, don’t load the entire object. Just select the columns you need:
var userNames = context.Users.Select(u => new { u.Id, u.Name }).ToList();
This reduces the size of the data returned and improves speed, especially when working with large tables.
2. Optimize Query Performance
Use Compiled Queries for Repeated Queries
If you run the same query many times with different inputs, EF compiles it each time. You can save time by compiling the query once and reusing it:
private static readonly Func<MyDbContext, int, User> GetUserById =
EF.CompileQuery((MyDbContext context, int id) =>
context.Users.FirstOrDefault(u => u.Id == id));
var user = GetUserById(context, 1);
Compiled queries skip repeated processing and make execution faster.
Prefer Bulk Operations for Large Datasets
If you have to insert or update a large number of records, don’t do it one-by-one in a loop. Instead, use bulk operations, which are much faster:
context.BulkInsert(users);
context.BulkUpdate(users);
You can use libraries like EFCore.BulkExtensions for this. It cuts down the number of times EF talks to the database.
3. Indexing and Query Optimization
Ensure Proper Indexing
Indexes help the database find data faster. If you search by certain columns often, you should add indexes to them:
[Index(nameof(Email))]
public class User {
public int Id { get; set; }
public string Email { get; set; }
}
You can also manually create indexes in your SQL database for even better control.
Analyze SQL Queries with SQL Profiler
Use tools like SQL Server Profiler or EF Core logging to see the actual SQL that EF runs:
context.Database.Log = Console.WriteLine;
This helps you find slow queries, remove extra joins, and select only the data you need.
4. Reduce Database Calls
Use Caching for Frequently Accessed Data
If your app reads the same data often, you can cache it in memory. This saves time and avoids hitting the database every time:
var cachedData = memoryCache.GetOrCreate("Users", entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
return context.Users.AsNoTracking().ToList();
});
Use tools like MemoryCache or Redis to store frequently used data.
Batch Queries Instead of Multiple Calls
When you need related data, don’t write multiple queries. Fetch everything in one go using .Include():
var orders = context.Orders.Include(o => o.Customer).ToList();
This makes fewer database calls and gets all needed data at once.
5. Optimize Transactions and Connection Management
Use Batching for SaveChanges()
Don’t call SaveChanges() inside a loop. Add all items first, then save them together:
foreach (var user in users)
{
context.Users.Add(user);
}
context.SaveChanges();
This way, all changes are sent to the database in one trip, which is faster.
Manage Database Connections Efficiently
using (var context = new MyDbContext())
{
var users = context.Users.ToList();
}
Using a using block ensures that the connection is closed after use.
6. Migrate to Latest EF Core Versions
Conclusion
-
Apps that follow EF optimization techniques can be up to 70% faster in database operations.
-
Memory usage can go down by 60% in apps that read a lot of data.
Collaborate with us
Contact us today to optimize your application’s performance.
Brijesh Hirapara
A highly skilled .NET Full Stack Developer proficient in MVC, .NET Core, C#, SQL, jQuery. Committed to delivering efficient, high-quality solutions by simplifying complex projects with technical expertise and innovative thinking.
Reply