首页 > 其他分享 >NopCommerce中缓存学习

NopCommerce中缓存学习

时间:2023-03-11 23:22:41浏览次数:44  
标签:缓存 cache db 更新 学习 NopCommerce test HttpContext nop

最近把后台管理程序换成nop方式。

在使用_productService.Update(M); 时碰到问题,更新不成功。

刚开始还以为是EF的问题,因为是先_productService.GetProductById(id), 再update,难道get的实体类不是要更新的数据吗?

然后查了下EF更新的三种情况:

1.最基本的,先查出来再更新,EF会跟踪查询的结果,看是否有新的更新,如果有只更新修改的字段,如果没有修改内容则不更新数据库。

            TestDbContext db = new TestDbContext();
            var test = db.Tests.Find(1);
            test.Remarks = "更新字段方法1";

            db.SaveChanges();            

 

2.比第一种情况少了查询步骤。先New一个实体类并且赋值,再通过dbcontext的db.Entry(test).State设置该实体类对应的状态是modified,然后savechange()即可,此方法会更新表的每个字段,没有赋值就是Null。

            TestDbContext db = new TestDbContext();
            Test test = new Test() { ID = 1, Remarks = "更新字段方法2" };
            db.Entry(test).State = System.Data.Entity.EntityState.Modified;

            db.SaveChanges();

 

3.也不用先查询该数据,而且不会更新全部字段,只更新设置了IsModified = true的字段。New一个实体类并赋值,db.Tests.Attach(test);把该实体类添加到dbcontext,然后db.Entry(test).Property("Remarks").IsModified = true;对需要修改的字段设置属性,只会对设置属性的字段更新。

复制代码
            TestDbContext db = new TestDbContext();
            Test test = new Test() { ID = 1, Remarks = "更新字段方法3" };
            db.Tests.Attach(test);
            db.Entry(test).Property("Remarks").IsModified = true;

            db.SaveChanges();
复制代码

使用 SQL Server Profiler 跟踪数据库发现_productService.GetProductById(id)这个步骤没有产生sql语句,进去该方法,猜测应该是缓存的问题,确定不是EF的问题。

_productService.GetProductById方法:

复制代码
        public M_Device GetProductById(int productId)
        {
            if (productId == 0)
                return null;

            string key = string.Format(BSRPRODUCTS_BY_ID_KEY, productId);
            return _cacheManager.Get(key, () => _productRepository.GetById(productId));
        }
复制代码

其中: _cacheManager.Get(key, () => _productRepository.GetById(productId)) 是先查 _cacheManager.Get<M_Device>(key)看是否有值,否则执行后面的lambda表达式。

调试发现_cacheManager.Get<M_Device>(key)一直有值,难怪更新不成功,是因为没有执行GetById方法。

查nop代码:

nop有三种缓存:HttpContextBase.Items键值对、Redis、MemoryCache。

在依赖注入程序里有:

 

复制代码
       if (config.RedisCachingEnabled)
            {
                builder.RegisterType<RedisConnectionWrapper>().As<IRedisConnectionWrapper>().SingleInstance();
                builder.RegisterType<RedisCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").InstancePerLifetimeScope();
            }
            else
            {
                builder.RegisterType<MemoryCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").SingleInstance();
            }
            builder.RegisterType<PerRequestCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_per_request").InstancePerLifetimeScope();
复制代码

Redis 和 MemoryCache 会二选一,我的程序中暂时使用的 MemoryCache 。

在CacheExtensions.cs里看到默认有效期是60分钟。

调试发现return _cacheManager.Get(key, () => _productRepository.GetById(productId)); 里的cache竟然是 MemoryCache(估计是因为在注入程序中把PerRequestCache的实例化注销了导致)。

builder.RegisterType<bsrProductService>().As<IbsrProductService>().InstancePerLifetimeScope();

一般service里的cache默认是PerRequestCache。如果要注入 MemoryCache需要传入参数:

builder.RegisterType<bsrProductController>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"));

查了下PerRequestCache的 HttpContextBase.Items键值对,

复制代码
   HttpContext基于HttpApplication的处理管道,由于HttpContext对象贯穿整个处理过程,所以,可以从HttpApplication处理管道的前端将状态数据传递到管道的后端,完成状态的传递任务。

  HttpContext的生命周期从服务器接收的HTTP请求开始到反应发送回客户端结束。

  在WebForm或类库(包括MVC)项目中,通过Current静态属性,就能够获得HttpContext的对象。

  HttpContext context = HttpContext.Current;
  如果是在Asp.net MVC的Controller中,通过this.HttpContext;就能获取到HttpContextBase对象。

  HttpContextBase context = this.HttpContext;
  如果是在MVC视图中可以这样得到:

  @Html.ViewContext.HttpContext
  在MVC中是HttpContextBase在WebForm中是HttpContext。
复制代码
HttpContext的Items是IDictionary键/值对的对象集合,在HttpRequest的生存期中共享。它只存在于HttpRequest中。

所以:

点击编辑进入详情页的时候虽然调用了_productService.GetProductById(id), 缓存了该条数据(HttpContextBase.Items缓存,客户端显示正常后缓存就结束了), 编辑数据点击保存后,

先调用 _productService.GetProductById(id) 即 return _cacheManager.Get(key, () => _productRepository.GetById(productId));  里的cache并没有该值,因为点击保存又是另外的HttpRequest了。再update,发现成功更新。

标签:缓存,cache,db,更新,学习,NopCommerce,test,HttpContext,nop
From: https://www.cnblogs.com/Alex80/p/17207339.html

相关文章