【问题标题】:.NET Caching with AutoFac.NET 缓存与 AutoFac
【发布时间】:2016-07-20 15:18:42
【问题描述】:

我正在使用 AutoFac 并有一个自定义缓存实现。当我注册缓存实现的类型时,我将缓存服务配置为 SingleInstance()。但是,这会提示数据库连接(使用 EF)出现问题,因为第二个并发请求会尝试访问已关闭的连接。

Builder.RegisterType<MyCachingDataService>().As<IMyCachingDataService>().SingelInstance();

因此我们删除了 SingleInstance() 并将其设置为每次调用的默认实例,现在的问题是,如果我们每次调用都执行一个实例,它有点违背缓存的目的,这样它的性能就会降低。

解决方法是什么,我做错了什么。

【问题讨论】:

  • 这与 AutoFac 无关。您还应该指定您使用的 EF 版本并发布了一些代码
  • 我刚刚更新了这个问题,显然我认为是AutoFac,因为我有连接问题以及我的缓存实现对象的单例性质。
  • 您可以在没有 Autofac 的情况下复制此问题。只需将您的实体设置为静态成员并尝试重用它们,您将遇到同样的问题。如果您尝试在加载了已释放的上下文的实体上使用未填充的导航属性,它将引发异常。

标签: c# .net caching autofac


【解决方案1】:

首先 dbcontext 不应该是单例的。但是,如果您在单例中有 dbcontext,它也将是单例。即使你没有单例数据库上下文。

您应该使用 Factory 来解决您的问题。您可以为自己创建一个工厂。每次询问 dbcontext,都会先询问工厂,工厂会返回 dbcontext(与 db context 的生命周期有关)。

所以你的缓存和工厂将是单例的,但不是 dbcontext。

Autofac 有自动生成的工厂。

您可以使用Dynamic Instantiation

但我建议你的缓存不应该有 dbcontext。您的服务(或其他)首先询问缓存,如果结果不存在,他们应该询问 db 并获取结果并将其保存到缓存中。缓存不应该对分贝负责。缓存只是负责将结果按键保存到内存,并从内存中按键返回结果。

您可以使用Aspect-Oriented Programming通过方法实现缓存系统。这对干净的代码很有好处。检查Postsharp

【讨论】:

    【解决方案2】:

    您应该缓存分离的实体。这样他们就不会尝试访问数据库。例如

    context.MyEntities.AsNoTracking().Where(...).ToList();
    

    查看这里了解更多详情。

    How do I detach objects in Entity Framework Code First?

    此代码将根据您使用的 EF 版本而有所不同。

    【讨论】:

    • 我想你误解了他问的缓存。他要求一般缓存而不是在上下文中缓存。一项服务会询问一些结果,他会将这些数据保存在内存中(或 redis vs),并且不会去 db 进行相同的询问让我们说 10 分钟。
    • @ErkanDemirel 无论是在内存中还是使用 HttpContext 缓存,EF 实体的缓存方式都没有关系,除非您专门从 EF 上下文中分离实体,然后尝试使用导航属性EF 上下文已被释放将导致异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 2023-01-12
    • 2012-05-21
    相关资源
    最近更新 更多