Simple optimization of EF Core

Keywords: C# Database SQL

;

Summary

This article is a relatively low and simple point of knowledge

1, Delayed Loading (Lazy Loading)

Postpone loading until data usage;Only when accessing methods such as ToList/ToArray/First/FirstOrDefault(), delayed loading of navigation properties, etc.Only load data

Example of delayed loading of navigation attributes using a proxy and virtual attributes

1, Install Microsoft.EntityFrameworkCore.Proxies using Nuget

2, Configure the model, using the virtual attribute

public class UserInfo
{
    public long Id { get; set; }
    public string UserName { get; set; }
    public int Age { get; set; }

    /// <summary>
    ///Delay loading using virtual objects, using the proxy object method when loading, note when using proxy;All navigation properties require virtual
    /// </summary>
    public virtual List<Employee> Employees { get; set; }
}

public class Employee
{
    public int Id { get; set; }

    public string Name { get; set; }
}

3, Modify the context configuration

/// <summary>
///Database Context
/// </summary>
public class DemoContext : DbContext
{

    private readonly string _connectionString;

    public DemoContext(string connectionString)
    {
        _connectionString = connectionString;
    }

    public virtual DbSet<UserInfo> UserInfo { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(_connectionString);
        }
        //Turn on delayed loading
        optionsBuilder.UseLazyLoadingProxies();
    }
}

Example, using the delayed loading method of the EF Core official scheme

1, use Nuget to install the Microsoft.EntityFrameworkCore.Abstractions package
2, Configure Model

public class UserInfo
{
    private ILazyLoader LazyLoader { get; set; }
    private UserInfo(ILazyLoader lazyLoader)
    {
        LazyLoader = lazyLoader;
    }
    public long Id { get; set; }
    public string UserName { get; set; }
    public int Age { get; set; }

    private ICollection<Employee> _employees;
     //Delayed loading can be done for specific attributes
    public ICollection<Employee> Employees
    {
        get
        {
            return LazyLoader?.Load(this, ref _employees);
        }
        set
        {
            _employees = value;
        }
    }

}

public class Employee
{
    public int Id { get; set; }

    public string Name { get; set; }
}

3, turn on optionsBuilder.UseLazyLoadingProxies() in the context configuration;

2, Abuse of Delayed Loading

EF Core to prevent abuse of delayed loading;Requires us to configure to turn on delayed loading

Delayed loading is used in scenarios where you are not sure if you need to load data immediately, or when you know you don't need to load data immediately

3, Entity Tracking

When an EFCore context returns a data record, [default] tracks the data record;SaveChanges saves changes when the SaveChanges method executes when changes are made to the data

When you query data that does not need to be modified, especially when you query large amounts of data without making changes, you can choose not to track to save money

1, Mode 1: Cancel trace lookup using AsNoTracking method when in use (recommended)

var query=_dbContext.UserInfo.AsNoTracking();

2, Mode 2: Configure Tracking Query Behavior

//Close
_dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
//open
_dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll;

4, Display compiled queries

Shows compilation, compared to normal queries, that compiled queries compile EF expressions only on the first call, and queries at the next run using the compiled results from the memory cache (that is, sql statements)

Explicitly compiled queries provide highly available scenarios that can improve query performance by using explicitly compiled queries

When our code needs to reuse previously executed queries, EF Core will use hash lookups and return compiled queries from the cache.We prefer to use compiled queries directly to bypass hash calculations and cache lookups

Scenarios where applicable (with unchanged query parameters): high concurrency;Large number of queries

Note: Currently only a single data can be returned, not a collection

Example:

var query = EF.CompileAsyncQuery((BusinessContext context, int id) => context.UserInfo.FirstOrDefault(a => a.Id == id);
var userInfo = query(_dbContext, 1);

Posted by Jay_Seagrave on Wed, 01 Sep 2021 09:51:47 -0700