caching recommendations & code samples

Topics: Web Client Software Factory, UIP Application Block discussion, User Forum
May 9, 2008 at 3:07 PM
Hi There,

Can anyone post code samples or recommend the approach to using caching with the WCSF?

Sean
May 9, 2008 at 3:15 PM
pbolduc provides an example here with Unit Test!
Jonathan provides an example here

Reference links pulled from a a site I'm working on
May 9, 2008 at 6:04 PM
I would recommend adding caching at the service or controller layers. Basically, the flow is something similar to this,

[Page/UserControl] -> [Presenter] -> [Controller] -> [Service] -> [Database / Web Service]

Services are 'stateless', as they are shared for all calls, ie they are singletons. Controllers are usually created new by Presenters. Presenters are created new by Pages/UserControls.

Depending on your caching needs, you could use HttpContext.Cache or you could use the Enterprise Library caching. I would recommend Enterprise Library caching.

Also there are a few distributed caching (cache your data across multiple machines), such as NCache (check out the free version NCache Express) http://www.alachisoft.com/ncache/ or indeXus.Net Shared Cache http://www.codeplex.com/SharedCache.

Regardless of the cache you want to use, you should consider the standard caching questions such as:
  • What cache key are you going to use?
  • How long should data be cached?
  • How will the cache be cleaned up?


seankerr wrote:
Can anyone post code samples or recommend the approach to using caching with the WCSF?

May 12, 2008 at 2:46 AM
Hi There,

Thanks for the posts they were extremely helpful. I came up with the following based on the other posts I read. I tried to take into account the questions you posted. Any more advice / help on my implementation would be appreciated.

Sean



#region Fields
        private CategorieService _controller;
        CacheItemRemovedCallback onRemove = null;

        private IHttpContextLocatorService contextLocator;
        private IList<WellcomRepository.BusinessEntities.Categorie> lstGenders;
        #endregion

        #region Properties
        private IHttpContext Context
        {
            get { return contextLocator.GetCurrentContext(); }
        }
        #endregion

        #region public Methods
        [InjectionMethod]
        public void InitializeServices([ServiceDependency] IHttpContextLocatorService contextLocator)
        {
            this.contextLocator = contextLocator;
        }

        public GendersViewPresenter([CreateNew] CategorieService controller)
        {
            _controller = controller;
        }

        public void RemoveItemFromCache(Object sender, EventArgs e) {
            if (Context.Cache["lstGenders"] != null)
                Context.Cache.Remove("lstGenders");
             }

        public override void OnViewInitialized()
        {
            if (Context.Cache["lstGenders"] == null)
            {
               lstGenders = _controller.GetGenders();
               View.lstGenders = lstGenders;

               Context.Cache.Insert("lstGenders", lstGenders, null, DateTime.Now.AddMinutes(2), Cache.NoSlidingExpiration, CacheItemPriority.High, onRemove);
            }
            else
            {
                View.lstGenders = (IList<WellcomRepository.BusinessEntities.Categorie>)Context.Cache["lstGenders"];
            }
        }



pbolduc wrote:
I would recommend adding caching at the service or controller layers. Basically, the flow is something similar to this,

[Page/UserControl] -> [Presenter] -> [Controller] -> [Service] -> [Database / Web Service]

Services are 'stateless', as they are shared for all calls, ie they are singletons. Controllers are usually created new by Presenters. Presenters are created new by Pages/UserControls.

Depending on your caching needs, you could use HttpContext.Cache or you could use the Enterprise Library caching. I would recommend Enterprise Library caching.

Also there are a few distributed caching (cache your data across multiple machines), such as NCache (check out the free version NCache Express) http://www.alachisoft.com/ncache/ or indeXus.Net Shared Cache http://www.codeplex.com/SharedCache.

Regardless of the cache you want to use, you should consider the standard caching questions such as:
  • What cache key are you going to use?
  • How long should data be cached?
  • How will the cache be cleaned up?


seankerr wrote:
Can anyone post code samples or recommend the approach to using caching with the WCSF?




May 12, 2008 at 3:18 PM
Looks reasonable. Not sure if it was intentional, but I noticed you do not set your callback handler, CacheItemRemovedCallback onRemove.  Also, the call back is used to notify an item been removed already, not to tell you that you should remove it.


seankerr wrote:
Hi There,

Thanks for the posts they were extremely helpful. I came up with the following based on the other posts I read. I tried to take into account the questions you posted. Any more advice / help on my implementation would be appreciated.

Sean
May 12, 2008 at 10:35 PM
Hi  pbolduc,

What would you change? This is my first time using the patterns and I would appreciate any advice that you might have.

Sean

pbolduc wrote:
Looks reasonable. Not sure if it was intentional, but I noticed you do not set your callback handler, CacheItemRemovedCallback onRemove.  Also, the call back is used to notify an item been removed already, not to tell you that you should remove it.


seankerr wrote:
Hi There,

Thanks for the posts they were extremely helpful. I came up with the following based on the other posts I read. I tried to take into account the questions you posted. Any more advice / help on my implementation would be appreciated.

Sean



May 14, 2008 at 3:57 PM
Edited May 14, 2008 at 4:09 PM

In my opinion, I would introduce a controller.  Your presenter would [CreateNew] the controller, the controller wraps all the cache logic and the controller has [ServiceDependency] on your service.  Darn, seems cut & paste may not preserve my formatting...
    public interface ICategorieService
    {
        IList<categorie> GetGenders();
    }

    public class CategorieService : ICategorieService
    {
        [CreateNew]
        public IList<categorie> GetGenders()
        {
            throw new NotImplementedException();
        }
    }

    public interface ICategorieController
    {
        IList<categorie> GetGenders();
    }

    public class CategorieController : ICategorieController
    {
        private const string genderCacheKey = "lstGenders";

        private IHttpContextLocatorService HttpContextLocatorService { get; set; }
        private ICategorieService CategorieService { get; set; }

        public CategorieController([ServiceDependency] IHttpContextLocatorService contextLocator,
            [ServiceDependency] ICategorieService categorieService)
        {
            HttpContextLocatorService = contextLocator;
            CategorieService = categorieService;
        }

        private IHttpContext Context { get { HttpContextLocatorService.GetCurrentContext(); } }

        public IList<categorie> GetGenders()
        {
            IList<categorie> genders = Context.Cache[genderCacheKey] as IList<categorie>;

            if (genders == null)
            {
                genders = CategorieService.GetGenders();
                Context.Cache.Insert(genderCacheKey, genders, null, DateTime.Now.AddMinutes(2), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
            }
            return genders;
        }
    }

seankerr wrote:
Hi  pbolduc,

What would you change? This is my first time using the patterns and I would appreciate any advice that you might have.

Sean
May 15, 2008 at 4:29 PM

Check out the Catalog Sweep project.

seankerr wrote:
Hi There,

Can anyone post code samples or recommend the approach to using caching with the WCSF?

Sean