what is the First & Second level caching in EF-core ?

what is the First & Second level caching in EF-core ?

In Entity Framework Core (EF Core), the terms "first level" and "second level" refer to the caching of entity instances.

First Level Cache: This is also known as the "local cache" or "context cache". EF Core uses a first level cache to keep track of entities that have been queried or added to the context. When you query for an entity, EF Core checks if it's already in the first level cache before sending a query to the database. If it finds the entity in the cache, it returns that entity rather than querying the database.

Suppose you have a DbContext class called MyContext that has a Blog entity and you want to retrieve all the blogs:

using (var context = new MyContext())

{

??var blogs = context.Blogs.ToList();

??var blog1 = context.Blogs.FirstOrDefault(b => b.Id == 1);

??var blog2 = context.Blogs.FirstOrDefault(b => b.Id == 2);

}

The first line retrieves all the blogs from the database and stores them in the local cache of the context. The second and third lines try to retrieve the blogs with Id 1 and 2 respectively, When the second line executes, EF Core checks the local cache of the context first. If the blog with Id 1 is already in the cache, EF Core returns it from the cache without querying the database. If the blog with Id 1 is not in the cache, EF Core executes a query against the database to retrieve it, adds it to the cache, and returns it to the calling code, similarly when the third line executes, EF Core checks the cache again for the blog with Id 2. If it's already in the cache, EF Core returns it from the cache. If it's not in the cache, EF Core queries the database, adds the blog to the cache, and returns it to the calling code.

EF Core uses the first level cache by default to help improve performance by reducing the number of database queries that need to be executed. However, there may be cases where you need to bypass the cache or manually control the cache behavior. In such cases, you can use techniques such as disabling tracking, using raw SQL queries, or implementing a custom caching strategy.

Second Level Cache: This is a global cache that sits on top of the first level cache. It stores the results of frequently executed queries, which can be reused across multiple instances of the context. When a query is executed, EF Core first checks the second level cache to see if the results are already available there. If the results are found in the second level cache, they are returned immediately without hitting the database.

The second level cache is not a default behavior in Entity Framework Core . and it needs to be added explicitly using third-party libraries or custom code. EF Core provides a flexible caching infrastructure that allows developers to implement their own caching solutions or use existing ones provided by the community. Here is an example of how to implement a simple second level cache using the MemoryCache class from the .NET Core caching library:

  1. Install the appropriate NuGet packages:

  • Microsoft.Extensions.Caching.Memory
  • Microsoft.Extensions.DependencyInjection

2 . In your Startup.cs file, add the following code to the ConfigureServices method:

services.AddMemoryCache();

services.AddDbContext<MyDbContext>(options =>

???options.UseSqlServer(Configuration.GetConnectionString("MyDb"))

??????????.UseMemoryCache(myCache));

This will configure the memory cache and add it to the DbContextOptionsBuilder using the UseMemoryCache method.

3 . In your DbContext class, override the OnModelCreating method and add the following code:

{

???base.OnModelCreating(modelBuilder);

?

???modelBuilder.Entity<MyEntity>()

???????.HasQueryFilter(e => !e.IsDeleted)

???????.Cacheable();

}

4.Use the Cache extension method to retrieve the cached data:

var myEntity = await _dbContext.MyEntities

???.Cacheable()

???.FirstOrDefaultAsync(e => e.Id == id);

This will retrieve the cached data if available, or query the database and cache the result if it's not already cached.

Note:

This example uses the MemoryCache provider. You can also use other caching providers, such as Redis or Memcached

second level caching is typically used in conjunction with other caching techniques, such as first level caching (caching data within an application's own memory) and distributed caching (caching data across multiple servers).

Second level caching can be implemented at the application level using various caching frameworks or libraries and implementing second level caching at the application level can be particularly useful for applications that handle large volumes of data or have complex data access patterns. It can help reduce the load on the data source, which can in turn improve the performance and scalability of the application.

In summary, first level cache is an in-memory cache maintained by the DbContext and is used to store query results for fast retrieval, while second level cache is an external cache that can be used to cache query results across different DbContext instances or applications, and can be configured to expire or be invalidated when the data is updated

Viachaslau Bakhtsin

Solution Architect | Tech Lead | .NET expert

4 个月

In this article, the description of the first-level cache is somewhat inaccurate and can lead to a misunderstanding of the change tracking mechanism, potentially causing errors during development. When executing the methods from the example: var blog1 = context.Blogs.FirstOrDefault(b => b.Id == 1); var blog2 = context.Blogs.FirstOrDefault(b => b.Id == 2); in reality, SQL queries will be sent to the database (this can be verified quite easily by investigating the app/DB logs) because EF Core is not omnipotent, and it cannot deduce from the lambda expression that it is required to return entities based on their PK. However, if EF Core sees during processing the result of the SQL command that an entry for the loaded entity already exists within the Change Tracker (compared by PK), it will then return the entity from that entry (with the old cached values, ignoring the new column values in the database). To achieve the behavior described in the article, you need to use the .Find()/.FindAsync() methods, which truly won’t execute a database query if the entry/entity with the specified PK is already loaded in the Change Tracker.

Maximilian Kenfenheuer

Manager @ BearingPoint | Leading Business Value Conversations

1 年

In your code sample you wrote the following: ".UseMemoryCache(myCache)" But where is "myCache" coming from?

Ahmed Rabi

Software Engineer

1 年

what if i used something like this what will be the result using (var context = new DbContext()){ var books = context.Books.Where(b=> b.Author == "ShakeSpear").ToList();//consider Ids 5-10 var book = context.Books.FirstOrDefault().Id; // this would be 1 or 5 ? var book1 = books.FirstOrDefault().Id; // this should be 5

回复
árpád Pollman

Software Engineer at Leica Geosystems AG

1 年

Hi Salem. I tried to implement this second level cache but I can't seem to figure out where .Cacheable() method come from? Is it part of some EF core extension nuget package?

回复

要查看或添加评论,请登录

Salem Naser的更多文章

社区洞察

其他会员也浏览了