Res*_*aos 1 caching ncache entity-framework-core asp.net-core ef-core-6.0
我看到大量关于人们努力让 EF 不发送缓存数据的帖子。我坐在这里想知道他们如何让它发送缓存数据......
以下是详细信息:使用 Entity Framework Core 6.0.6 的 .NET 6.0 上的 ASP.NET Core 最新版本。通过 Swagger 站点页面测试控制器方法。DbContext 具有作用域并注入依赖项。未使用 AsNoTracking。
该方法非常简单_DbContext.Set.ToListAsync()。
我希望第二次调用具有“陈旧”数据,即与第一次调用相同的数据。但是,它有我从数据库中更新的数据!?第二次调用要快得多,我认为这是因为 EF 缓存了我的查询和元数据,但它似乎没有缓存查询的实际结果。
根据我的测试,它看起来只会缓存同一请求中的结果。一旦请求完成,DbContext 就会被释放,然后结果缓存就会消失。正确的?因此,如果我想在不同的 Web 请求之间保留结果缓存,那么我必须通过 NCache、其他一些包或自己编写代码来实现自己的缓存?
实体框架依赖于跟踪机制(请参阅此和此)。它本身不是缓存,但它可以产生类似的效果,尽管主要目标之一是跟踪更改,以便将它们传播到数据库。
更改跟踪“绑定”到上下文的具体实例(即不在不同实例/全局之间共享)。变更跟踪的重要功能之一是身份解析:
由于跟踪查询使用更改跟踪器,因此 EF Core 将在跟踪查询中进行身份解析。当具体化实体时,EF Core 将从更改跟踪器返回相同的实体实例(如果已被跟踪)。如果结果多次包含相同的实体,则每次出现都会返回相同的实例。无跟踪查询不使用更改跟踪器,也不进行身份解析。因此,即使结果中多次包含同一实体,您也会返回实体的新实例。
如果数据库在同一上下文中的请求之间“外部”更新,这可能会导致数据过时:
using (var ctx1 = new AppContext())
{
var entity = await ctx1.SomeEntity
.Where(e => e.Id == 1)
.FirstOrDefaultAsync();
using (var ctx2 = new AppContext())
{
var theSameEntity = await ctx2.SomeEntity
.Where(e => e.Id == 1)
.FirstOrDefaultAsync();
theSameEntity.SomeTextField = "Updated"; // assuming it had another value
await ctx2.SaveChangesAsync();
}
var entity1 = await ctx1.SomeEntity
.Where(e => e.Id == 1)
.FirstOrDefaultAsync()
var referenceEquals = object.ReferenceEquals(entity, entity1); // True
var field = entity1.SomeTextField; // field will have the original value, not "Updated"
}
Run Code Online (Sandbox Code Playgroud)
第二次调用要快得多,我相信这是因为 EF 缓存了我的查询和元数据
其潜在原因有多种:
还有几个因素影响“启动时间”,即在应用程序中第一次使用DbContext该类型时执行第一个操作的时间。DbContext
创建
DbContext实例不会导致 EF 模型被初始化,导致模型初始化的典型第一个操作包括调用DbContext.Add或执行第一个查询。
但它似乎没有缓存查询的实际结果。
它同时是部分正确和部分错误的。如前所示 - 如果数据实际上已更改,EF 将不会更新跟踪的实体。但如果数据被删除,EF 会发现:
using (var ctx1 = new AppContext())
{
var entity = await ctx1.SomeEntity
.Where(e => e.Id == 1)
.FirstOrDefaultAsync();
using (var ctx2 = new AppContext())
{
var theSameEntity = await ctx2.SomeEntity
.Where(e => e.Id == 1)
.FirstOrDefaultAsync();
ctx2.DeliveryComment.Remove(theSameEntity); // remove
await ctx2.SaveChangesAsync();
}
var entity1 = await ctx1.SomeEntity
.Where(e => e.Id == 1)
.FirstOrDefaultAsync()
var isNull = entity1 == null; // True
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7820 次 |
| 最近记录: |