Closed fishen closed 7 years ago
How do you know it doesn't work? How did you test it? To test it, you should log the produced SQL or you can provide an additional parameter here
var debugInfo = new EFCacheDebugInfo();
var list = db.HttpLogs.Take(1000).Cacheable(debugInfo).ToList();
And then check the value of debugInfo.IsCacheHit
. It should be false
for the fist call and true
for the second call. Also it will be false
after the cache invalidation.
thanks @VahidN
@VahidN I am having the same trouble. I have checked with the debugInfo.IsCacheHit
and it returns false even after numerous times.
Following is my configuration:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Other code is stripped for clarity
// Add Redis cache service provider
services.AddEFSecondLevelCache();
AddRedisCacheServiceProvider(services);
}
private static void AddRedisCacheServiceProvider(IServiceCollection services)
{
var jss = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
const string redisConfigurationKey = "redis";
services.AddSingleton(typeof(ICacheManagerConfiguration),
new CacheManager.Core.ConfigurationBuilder()
.WithJsonSerializer(jss, jss)
.WithUpdateMode(CacheUpdateMode.Up)
.WithRedisConfiguration(redisConfigurationKey, config =>
{
config.WithAllowAdmin()
.WithDatabase(0)
.WithEndpoint("localhost", 6379);
})
.WithMaxRetries(100)
.WithRetryTimeout(50)
.WithRedisCacheHandle(redisConfigurationKey)
.WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(10))
.Build());
services.AddSingleton(typeof(ICacheManager<>), typeof(BaseCacheManager<>));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseEFSecondLevelCache();
//other code is stripped for clarity
}
Following code is to get the the list of objects:
protected override async Task<object> OnHandleAsync(RestGetListRequest<TEntity, TGetModel> message,
CancellationToken cancellationToken)
{
var results = UnitOfWork.GetRepository<TEntity>().GetAll();
var debugInfo = new EFCacheDebugInfo();
var mapped = await results.Cacheable(debugInfo).ProjectTo<TGetModel>(Mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
return mapped;
}
DbContext is overriding the following:
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
var changedEntityNames = this.GetChangedEntityNames();
ChangeTracker.AutoDetectChangesEnabled = false; // for performance reasons, to avoid calling DetectChanges() again.
var result = base.SaveChanges();
ChangeTracker.AutoDetectChangesEnabled = true;
this.GetService<IEFCacheServiceProvider>().InvalidateCacheDependencies(changedEntityNames);
return result;
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
ChangeTracker.DetectChanges();
var changedEntityNames = this.GetChangedEntityNames();
ChangeTracker.AutoDetectChangesEnabled = false; // for performance reasons, to avoid calling DetectChanges() again.
var result = base.SaveChangesAsync(cancellationToken);
ChangeTracker.AutoDetectChangesEnabled = true;
this.GetService<IEFCacheServiceProvider>().InvalidateCacheDependencies(changedEntityNames);
return result;
}
Base class library responsible for getting the results is using the following:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Autofac" Version="4.8.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.2" />
<PackageReference Include="AutoMapper" Version="7.0.1" />
<PackageReference Include="AutoMapper.Attributes" Version="6.0.1" />
<PackageReference Include="EFSecondLevelCache.Core" Version="1.6.1" />
<PackageReference Include="EntityFrameworkCore.Triggers" Version="1.1.1" />
<PackageReference Include="FluentValidation" Version="7.6.104" />
<PackageReference Include="MediatR" Version="5.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.UnitOfWork" Version="2.0.4" />
</ItemGroup>
</Project>
and ASP.NET Core Web API is using the following:
<ItemGroup>
<PackageReference Include="EFSecondLevelCache.Core" Version="1.6.0" />
<PackageReference Include="CacheManager.Core" Version="1.1.2" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Caching.Memory" Version="1.1.2" />
<PackageReference Include="CacheManager.StackExchange.Redis" Version="1.1.2" />
<PackageReference Include="CacheManager.Serialization.Json" Version="1.1.2" />
</ItemGroup>
Note:
Upon further investigation, I found that if I remove ProjectTo<TGetModel>(Mapper.ConfigurationProvider)
from the LINQ it works fine.
It won't work with ProjectTo
of auto-mapper. the Cacheable
method needs to evaluate the expression tree to find dependencies and also its hash and it's not possible with the ProjectTo
method.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related problems.
I used redis as cache provider but it dosen't work, i can't find any key in redis db, so I switched to another model(WithMicrosoftMemoryCacheHandle), It does not seem to work too. I wrote two action for compare cache and nocache, but the time-consuming seems almost. I need your help @VahidN .