首页 > 解决方案 > 从.net core 2.1中的单例服务注入范围服务

问题描述

我有一个缓存助手。当我将 CacheHelper 的依赖项添加到使用“AddScoped”启动时,它正在工作。但是,CacheHelper.cs正在为每个请求运行。所以,我转换为“AddSingleton”,如下所示。但是我遇到了一个错误,例如: Cannot consume scoped service 'MyProject.DataAccess.IUnitOfWork' from singleton 'MyProject.Caching.ICacheHelper'我该如何解决这个问题?

启动程序

public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();
        services.AddScoped<IUnitOfWork, UnitOfWork>();
        services.AddScoped<IJwtHelper, JwtHelper>();
        services.AddScoped<IAuditHelper, AuditHelper>();
        services.TryAdd(ServiceDescriptor.Singleton<IMemoryCache, MemoryCache>());
        services.AddSingleton<ICacheHelper, CacheHelper>();
        services.AddMvc();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    }

缓存助手.cs

public class CacheHelper : ICacheHelper
{
    private readonly IUnitOfWork unitOfWork;
    public IMemoryCache Cache { get; }

    public CacheHelper(IUnitOfWork unitOfWork, IMemoryCache cache)
    {
        this.unitOfWork = unitOfWork;
        Cache = cache;
    }

    public void SetCommonCacheItems()
    {
        var cities = unitOfWork.CityRepo.GetAll();
        Cache.Set("cities", cities);

        string obj;
        Cache.TryGetValue<string>("cities", out obj);
    }

    public string GetCities()
    {
        string obj;
        Cache.TryGetValue<string>("cities", out obj);

        return obj;
    }
}

标签: c#asp.net-web-apiasp.net-core.net-core

解决方案


你以前的方式是正确的。ICacheHelper应该而且必须范围。

只是您的缓存实现是错误的。获取城市将被调用,它检查缓存。如果没有找到,它将获取数据并将其放入缓存中。

public class CacheHelper : ICacheHelper
{
    private readonly IUnitOfWork unitOfWork;
    public IMemoryCache Cache { get; }

    public CacheHelper(IUnitOfWork unitOfWork, IMemoryCache cache)
    {
        this.unitOfWork = unitOfWork;
        Cache = cache;
    }

    public string GetCities()
    {
        if(!Cache.TryGetValue<string>("cities", string out cities))
        {
            // not found in cache, obtain it
            cities = unitOfWork.CityRepo.GetAll();
            Cache.Set("cities", cities);
        }

        return cities;
    }
}

你不需要SetCommonCacheItems()方法。重要的是它IMemoryCache是静态的,因为它将包含数据。由于数据库,UoW 必须确定范围,否则您会出现内存泄漏(尤其是在使用 EF Core 时,因为它缓存/跟踪实体)。


推荐阅读