C# 如何使用IoC在异步服务中缓存?
我有一个项目,我们使用一个服务架构,用Ninject来解决我们的服务。我们几乎所有的服务都使用异步 现在,我想向几个服务添加缓存 我从未在异步方法中使用过缓存,因此我不确定如何使用它。我只知道我当前以HttpContext的形式获取此错误。Current为null: 那么,我应该采取什么策略来实现这一目标呢? 我的IoC设置:NinjectWebCommon.cs:C# 如何使用IoC在异步服务中缓存?,c#,asp.net-mvc,caching,asynchronous,C#,Asp.net Mvc,Caching,Asynchronous,我有一个项目,我们使用一个服务架构,用Ninject来解决我们的服务。我们几乎所有的服务都使用异步 现在,我想向几个服务添加缓存 我从未在异步方法中使用过缓存,因此我不确定如何使用它。我只知道我当前以HttpContext的形式获取此错误。Current为null: 那么,我应该采取什么策略来实现这一目标呢? 我的IoC设置:NinjectWebCommon.cs: private static void RegisterServices(IKernel kernel) {
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<Context>().To<Context>().InRequestScope();
kernel.Bind<UserManager<User>>().To<UserManager>().InTransientScope();
kernel.Bind<IUserTokenProvider<User, string>>().ToMethod((x) =>
{
var provider = OwinConfig.DataProtectionProvider;
return new DataProtectorTokenProvider<User>(provider.Create("ASP.NET Identity"));
}).InTransientScope();
kernel.Bind<ICacheService>().To<HttpCache>();
kernel.Bind<IUserService>().To<UserService>();
// Lots of nice services
}
缓存服务:
public interface ICacheService
{
object GetById(string cacheKey);
object Create(string cacheKey, object obj);
object Create(string cacheKey, object obj, DateTime expire);
void Delete(string cacheKey);
void DeleteByContaining(string containing);
string GetCacheKey(string methodName, string value);
bool ContainsKey(string cacheKey);
}
public class HttpCache : ICacheService
{
private static readonly ILog logger = LogManager.GetLogger(typeof (HttpCache));
public object GetById(string cacheKey)
{
if (ContainsKey(cacheKey))
{
return HttpContext.Current.Cache[cacheKey];
}
return null;
}
public object Create(string cacheKey, object obj)
{
return Create(cacheKey, obj, DateTime.UtcNow.AddHours(5));
}
public object Create(string cacheKey, object obj, DateTime expire)
{
if (!ContainsKey(cacheKey))
{
HttpContext.Current.Cache.Insert(cacheKey,
obj,
null,
expire,
Cache.NoSlidingExpiration);
}
return GetById(cacheKey);
}
public void Delete(string cacheKey)
{
HttpContext.Current.Cache.Remove(cacheKey);
}
public void DeleteByContaining(string containing)
{
List<string> deleteList = new List<string>();
HttpContext oc = HttpContext.Current;
// find all cache keys in the system... maybe insane? I don't know lol
IDictionaryEnumerator en = oc.Cache.GetEnumerator();
while (en.MoveNext())
{
var k = en.Key.ToString();
if (k.Contains(containing))
{
deleteList.Add(k);
}
}
foreach (var del in deleteList)
{
Delete(del);
}
}
public bool ContainsKey(string cacheKey)
{
return HttpContext.Current.Cache[cacheKey] != null;
}
public string GetCacheKey(string methodName, string value)
{
return string.Format("{0}_{1}", methodName, value);
}
}
公共类HttpCache:ICacheService
{
私有静态只读ILog logger=LogManager.GetLogger(typeof(HttpCache));
公共对象GetById(字符串缓存键)
{
if(ContainsKey(cacheKey))
{
返回HttpContext.Current.Cache[cacheKey];
}
返回null;
}
公共对象创建(字符串缓存键,对象对象obj)
{
返回Create(cacheKey,obj,DateTime.UtcNow.AddHours(5));
}
创建公共对象(字符串cacheKey、对象obj、DateTime expire)
{
如果(!ContainsKey(cacheKey))
{
HttpContext.Current.Cache.Insert(cacheKey,
obj,
无效的
到期,
Cache.NoSlidingExpiration);
}
返回GetById(cacheKey);
}
公共无效删除(字符串缓存键)
{
HttpContext.Current.Cache.Remove(cacheKey);
}
公共void DeleteByContaining(字符串包含)
{
List deleteList=新列表();
HttpContext oc=HttpContext.Current;
//找到系统中的所有缓存密钥…可能是疯了?我不知道哈哈
IDictionaryEnumerator en=oc.Cache.GetEnumerator();
while(en.MoveNext())
{
var k=en.Key.ToString();
如果(k.Contains(containing))
{
删除列表。添加(k);
}
}
foreach(deleteList中的变量del)
{
删除(del);
}
}
公共bool ContainsKey(字符串缓存键)
{
返回HttpContext.Current.Cache[cacheKey]!=null;
}
公共字符串GetCacheKey(字符串方法名、字符串值)
{
返回string.Format(“{0}{1}”,方法名,值);
}
}
我的来电者:
public async Task<City> GetById(int id)
{
var cacheKey = _cacheService.GetCacheKey(MethodBase.GetCurrentMethod().Name, id.ToString());
if (!_cacheService.ContainsKey(cacheKey))
{
var city = await _db.Cities.FirstAsync(c => c.Id == id);
_cacheService.Create(cacheKey, city);
return city;
}
return (City)_cacheService.GetById(cacheKey);
}
public异步任务GetById(int-id)
{
var cacheKey=_cacheService.GetCacheKey(MethodBase.GetCurrentMethod().Name,id.ToString());
if(!\u cacheService.ContainsKey(cacheKey))
{
var city=await _db.Cities.FirstAsync(c=>c.Id==Id);
_创建(cacheKey,城市);
回归城市;
}
return(City)\u cacheService.GetById(cacheKey);
}
HttpContext.Current.Cache是访问ASP.Net全局缓存对象的几个快捷方式之一(请求生存时间的另一个快捷方式是)。如果需要在请求外部访问缓存,请使用。(也包括在本手册中)
注:
- 请注意,您没有得到
这一事实可能是更大问题的症状-您可能希望代码运行时设置HttpContext.Current
,但它不是,以及区域性。。。对于您来说,这是否确实是一个问题尚待解决,但至少要检查您的代码是否意外地使用了HttpContext
,.ConfigureAwait(false)
任务。手动运行
或安排线程池上的工作
- 虽然从缓存中添加/读取单个项是线程安全的,但当您希望多个项保持一致时,请小心—您可能需要锁定
- 小心不要将特定于用户的数据放在缓存中,尤其是当您的缓存处于IOC级别,并且您没有直接信息知道结果是否特定于用户时
- 请注意,您没有得到
这一事实可能是更大问题的症状-您可能希望代码运行时设置HttpContext.Current
,但它不是,以及区域性。。。对于您来说,这是否确实是一个问题尚待解决,但至少要检查您的代码是否意外地使用了HttpContext
,.ConfigureAwait(false)
任务。手动运行
或安排线程池上的工作
- 虽然从缓存中添加/读取单个项是线程安全的,但当您希望多个项保持一致时,请小心—您可能需要锁定
- 小心不要将特定于用户的数据放在缓存中,尤其是当您的缓存处于IOC级别,并且您没有直接信息知道结果是否特定于用户时
- 请注意,您没有得到
这一事实可能是更大问题的症状-您可能希望代码运行时设置HttpContext.Current
,但它不是,以及区域性。。。对于您来说,这是否确实是一个问题尚待解决,但至少要检查您的代码是否意外地使用了HttpContext
,.ConfigureAwait(false)
任务。手动运行
或安排线程池上的工作
- 虽然从缓存中添加/读取单个项是线程安全的,但当您希望多个项保持一致时,请小心—您可能需要锁定
- 小心不要将特定于用户的数据放在缓存中,特别是当您的缓存处于IOC级别,并且您没有直接信息知道结果是否为u