SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Guru pinch's Avatar
    Join Date
    Mar 2005
    Posts
    688
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Clearing Data Cache (Non-Programatically)

    I use data caching quite liberally in my .NET application. However, when debugging I often need to clear the data cache for testing purposes, such as when I change something at a lower-layer that I need to re-verify at the UI-level.

    Is there any way to clear the data cache without actually doing so programmatically, maybe through Visual Studio? I imagine I could place a button in an administrative area of my application, when clicked, would clear all data cache being used by the application, but is that essentially the only other option besides just waiting for the cache expiration timer to expire?

  2. #2
    SitePoint Evangelist
    Join Date
    Apr 2008
    Location
    Dublin, Ireland
    Posts
    461
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Rebuilding the app/site or editing the web.config to force an app restart normally does it for me.

  3. #3
    SitePoint Guru pinch's Avatar
    Join Date
    Mar 2005
    Posts
    688
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Changing the web.config seemed to do the trick just fine. Thanks.

  4. #4
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Depending on the app, I tend to build a cache management tool into the admin. It comes in handy from time to time.

    Moreover, anything to do with caching is also configuration driven, so in development mode the cache gets disabled in general.

  5. #5
    SitePoint Guru pinch's Avatar
    Join Date
    Mar 2005
    Posts
    688
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Moreover, anything to do with caching is also configuration driven, so in development mode the cache gets disabled in general.
    That's a good idea. Maybe add a setting to the web.config to indicate the state of my application (development vs production). I would check this setting and subsequently turn on/off caching accordingly?

  6. #6
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Personally, I tend not to have a develop mode switch but rather make a nice, rich configuration layer and keep separate copies of configurations in the source repository. Mich cleaner than having "development" modes in general.

  7. #7
    SitePoint Guru pinch's Avatar
    Join Date
    Mar 2005
    Posts
    688
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by wwb_99 View Post
    Personally, I tend not to have a develop mode switch but rather make a nice, rich configuration layer and keep separate copies of configurations in the source repository. Mich cleaner than having "development" modes in general.
    Could that be as simple as having multiple web.config's that you include/exclude based on where the application lives? That'd be much easier than what I'm doing but there would be the issue of naming conflicts. Do you have any references for building a 'configuration layer'?

  8. #8
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Can't think of a reference off the top of my head. Generally what we use are custom ConfigurationSections for the application-specific settings. Much cleaner than a mess of AppSettings, although AppSettings wrapped up in a static class is definitely better than nothing. The big advantage of ConfigurationSections is they are a PODO at heart so you can easily create a mock for testing and not have config file dependence issues.

    Insfar as switching, we just make copies of the appropriate files for each environment and keep them version controlled with the project. Deployment just involves copying in the appropriate configuration file.

    One trick that can help this is using the configSource attribute to separate out the changing sections versus the constant sections. IE--your production application is probably not going to change which HttpModules it is using, but it will change the database. So in web.config, the database connection info looks like this:

    Code:
    <connectionStrings configSource="connectionstrings.config" />
    And you just have a separate production copy for connectionstrings.config.

  9. #9
    SitePoint Guru pinch's Avatar
    Join Date
    Mar 2005
    Posts
    688
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Can't think of a reference off the top of my head. Generally what we use are custom ConfigurationSections for the application-specific settings. Much cleaner than a mess of AppSettings, although AppSettings wrapped up in a static class is definitely better than nothing. The big advantage of ConfigurationSections is they are a PODO at heart so you can easily create a mock for testing and not have config file dependence issues.
    Ok I'm currently doing that now. I have a custom configuration section:

    Code ASP:
    	<cheatSheetWarRoom defaultConnectionStringName="LocalSqlServer" enableAdvertisements="true">
    		<contactForm mailTo="admin@cheatsheetwarroom.com" mailCC="bperniciaro@gmail.com"/>
    		<sheets pageSize="25" providerType="BP.CheatSheetWarRoom.DAL.SqlClient.SqlSheetsProvider" enableCaching="true" cacheDuration="300" defaultSportCode="FOO" defaultQBsPerSheet="32" defaultRBsPerSheet="50" defaultWRsPerSheet="50" defaultTEsPerSheet="32" defaultKsPerSheet="32" defaultDEFsPerSheet="32"/>
    	</cheatSheetWarRoom>

    And a custom class for mapping to these settings:

    Code ASP:
    namespace BP.CheatSheetWarRoom
    {
      /// <summary>
      /// Summary description for ConfigSection
      /// </summary>
      public class CheatSheetWarRoomSection : ConfigurationSection
      {
        /// <summary>
        /// This property is decorated with the ConfigurationPropery attribute to indicate that it needs to
        /// be filled with settings read from the webconfig file
        /// </summary>
        [ConfigurationProperty("defaultConnectionStringName", DefaultValue = "LocalSqlServer")]
        public string DefaultConnectionStringName
        {
          get { return (string)base["defaultConnectionStringName"]; }
          set { base["connectionStdefaultConnectionStringNameringName"] = value; }
        }
     
        [ConfigurationProperty("defaultCacheDuration", DefaultValue = "600")]
        public int DefaultCacheDuration
        {
          get { return (int)base["defaultCacheDuration"]; }
          set { base["defaultCacheDuration"] = value; }
        }
     
        [ConfigurationProperty("enableAdvertisements", DefaultValue = "false")]
        public bool EnableAdvertisements
        {
          get { return (bool)base["enableAdvertisements"]; }
          set { base["enableAdvertisements"] = value; }
        }
     
     
        [ConfigurationProperty("contactForm", IsRequired=true)]
        public ContactFormElement ContactForm
        {
          get { return (ContactFormElement)base["contactForm"]; }
        }
     
        //[ConfigurationProperty("tellFriendForm", IsRequired = true)]
        //public TellFriendFormElement TellFriend
        //{
        //  get { return (TellFriendFormElement)base["tellFriendForm"]; }
        //}
     
     
        [ConfigurationProperty("sheets", IsRequired = true)]
        public SheetsElement Sheets
        {
          get { return (SheetsElement)base["sheets"]; }
        }
     
      }
     
      /// <summary>
      /// CONTACT ELEMENT
      /// </summary>
      public class ContactFormElement : ConfigurationElement
      {
     
        [ConfigurationProperty("mailSubject", DefaultValue="Mail from CSWR: {0}")]
        public string MailSubject
        {
          get { return (string)base["mailSubject"]; }
          set { base["mailSubject"] = value; }
        }
     
        [ConfigurationProperty("mailTo", IsRequired=true)]
        public string MailTo
        {
          get { return (string)base["mailTo"]; }
          set { base["mailTo"] = value; }
        }
     
        [ConfigurationProperty("mailCC")]
        public string MailCC
        {
          get { return (string)base["mailCC"]; }
          set { base["mailCC"] = value; }
        }
     
      }
     
     
     
     
      public class SheetsElement : ConfigurationElement
      {
     
        [ConfigurationProperty("connectionStringName")]
        public string ConnectionStringName
        {
          get { return (string)base["connectionStringName"]; }
          set { base["connectionStringName"] = value; }
        }
     
        public string ConnectionString
        {
          get
          {
            // Return the base class' ConnectionString property.
            // The name of the connection string to use is retrieved from the site's 
            // custom config section and is used to read the setting from the <connectionStrings> section
            // If no connection string name is defined for the <articles> element, the
            // parent section's DefaultConnectionString prop is used.
            string connStringName = (string.IsNullOrEmpty(this.ConnectionStringName) ?
               Globals.Settings.DefaultConnectionStringName : this.ConnectionStringName);
            return WebConfigurationManager.ConnectionStrings[connStringName].ConnectionString;
          }
        }
     
        [ConfigurationProperty("providerType", DefaultValue = "BP.CheatSheetWarRoom.DAL.SqlClient.SqlSheetsProvider")]
        public string ProviderType
        {
          get {return (string)base["providerType"]; }
          set { base["providerType"] = value; }
        }
     
        [ConfigurationProperty("pageSize", DefaultValue = "5")]
        public string PageSize
        {
          get { return (string)base["pageSize"]; }
          set { base["pageSize"] = value; }
        }
     
        [ConfigurationProperty("enableCaching", DefaultValue = "true")]
        public bool EnableCaching
        {
          get { return (bool)base["enableCaching"]; }
          set { base["enableCaching"] = value; }
        }
     
     
        [ConfigurationProperty("cacheDuration")]
        public int CacheDuration
        {
          get
          {
            int duration = (int)base["cacheDuration"];
            return (duration > 0 ? duration : Globals.Settings.DefaultCacheDuration);
          }
          set { base["cacheDuration"] = value; }
        }
     
     
        [ConfigurationProperty("defaultQBsPerSheet", DefaultValue = "32")]
        public int DefaultQBsPerSheet
        {
          get { return (int)base["defaultQBsPerSheet"]; }
          set { base["defaultQBsPerSheet"] = value; }
        }
     
        [ConfigurationProperty("defaultQBStatCodes", DefaultValue = "GAM,PAYD,PATD,RUYD,RUTD,INT,FUM,TFP,FPPG")]
        public string DefaultQBStatCodes
        {
          get { return (string)base["defaultQBStatCodes"]; }
          set { base["defaultQBStatCodes"] = value; }
        }
     
        [ConfigurationProperty("defaultRBsPerSheet", DefaultValue = "50")]
        public int DefaultRBsPerSheet
        {
          get { return (int)base["defaultRBsPerSheet"]; }
          set { base["defaultRBsPerSheet"] = value; }
        }
     
        [ConfigurationProperty("defaultRBStatCodes", DefaultValue = "GAM,RUYD,RUTD,REYD,RETD,FUM,TFP,FPPG")]
        public string DefaultRBStatCodes
        {
          get { return (string)base["defaultRBStatCodes"]; }
          set { base["defaultRBStatCodes"] = value; }
        }
     
        [ConfigurationProperty("defaultWRsPerSheet", DefaultValue = "70")]
        public int DefaultWRsPerSheet
        {
          get { return (int)base["defaultWRsPerSheet"]; }
          set { base["defaultWRsPerSheet"] = value; }
        }
     
        [ConfigurationProperty("defaultWRStatCodes", DefaultValue = "GAM,RUYD,RUTD,REYD,RETD,FUM,TFP,FPPG")]
        public string DefaultWRStatCodes
        {
          get { return (string)base["defaultWRStatCodes"]; }
          set { base["defaultWRStatCodes"] = value; }
        }
     
        [ConfigurationProperty("defaultTEsPerSheet", DefaultValue = "32")]
        public int DefaultTEsPerSheet
        {
          get { return (int)base["defaultTEsPerSheet"]; }
          set { base["defaultTEsPerSheet"] = value; }
        }
     
        [ConfigurationProperty("defaultTEStatCodes", DefaultValue = "GAM,RUYD,RUTD,REYD,RETD,FUM,TFP,FPPG")]
        public string DefaultTEStatCodes
        {
          get { return (string)base["defaultTEStatCodes"]; }
          set { base["defaultTEStatCodes"] = value; }
        }
     
        [ConfigurationProperty("defaultKsPerSheet", DefaultValue = "32")]
        public int DefaultKsPerSheet
        {
          get { return (int)base["defaultKsPerSheet"]; }
          set { base["defaultKsPerSheet"] = value; }
        }
     
        [ConfigurationProperty("defaultKStatCodes", DefaultValue = "GAM,MAFG,MIFG,MAXP,MIXP,TFP,FPPG")]
        public string DefaultKStatCodes
        {
          get { return (string)base["defaultKStatCodes"]; }
          set { base["defaultKStatCodes"] = value; }
        }
     
        [ConfigurationProperty("defaultDEFsPerSheet", DefaultValue = "32")]
        public int DefaultDEFsPerSheet
        {
          get { return (int)base["defaultDEFsPerSheet"]; }
          set { base["defaultDEFsPerSheet"] = value; }
        }
     
        [ConfigurationProperty("defaultDFStatCodes", DefaultValue = "GAM,FREC,INT,SACK,DTD,PA,TFP,FPPG")]
        public string DefaultDFStatCodes
        {
          get { return (string)base["defaultDFStatCodes"]; }
          set { base["defaultDFStatCodes"] = value; }
        }
     
        [ConfigurationProperty("defaultSportCode", DefaultValue = "FOO")]
        public string DefaultSportCode
        {
          get { return (string)base["defaultSportCode"]; }
          set { base["defaultSportCode"] = value; }
        }
     
      }
     
    }



    Insfar as switching, we just make copies of the appropriate files for each environment and keep them version controlled with the project. Deployment just involves copying in the appropriate configuration file.
    Tell me if I'm on the right track:

    I created 4 versions of my web.config for my needed configurations:

    web.config.local.exclude
    web.config.dev.exclude
    web.config.test.exclude
    web.config.prod.exclude

    Depending on my configuration needs, I simply 'include' the appropriate web.config file.

    In order to avoid changing the above web.configs, I create 4 other configuration files which contain only connection strings:

    ConnectionStringsLocal.config
    ConnectionStringsDev.config
    ConnectionStringsTest.config
    ConnectionStringsProd.config

    I then use the configSource of each respective web.config to point to the appropriate connection string configuration file.

    So if I wanted to move my code from test to production, I would only have to

    1. Rename the [test] web.config to web.config.test.exclude
    2. Rename web.config.prod.exclude to web.config
    3. Update ConnectionStringsProd.config as needed


    I'm not sure what I get out of splitting out the connection strings, other than the fact that the file I have to edit is short and simple. If I have to change the connection string it has to happens somewhere.
    Last edited by pinch; Jun 3, 2009 at 09:33. Reason: further developments

  10. #10
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    That could work. I tend to use folders rather than manipulate file names, but you can get there either way. One thing you do not want on production is config files that don't end in .config. IIS gives a HTTP forbidden return if you request a .config file, whereas someone might be able to read your .excludes.

    The advantage to separating out bits is that one can oftentimes get to a point where the web.config doesn't chage between settings, but the other bits might. Typically, I change the build action on the changable config files to none, then add the correct configs to the installer package.

  11. #11
    SitePoint Guru pinch's Avatar
    Join Date
    Mar 2005
    Posts
    688
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by wwb_99 View Post
    That could work. I tend to use folders rather than manipulate file names, but you can get there either way.
    How do you use folders?

    One thing you do not want on production is config files that don't end in .config. IIS gives a HTTP forbidden return if you request a .config file, whereas someone might be able to read your .excludes.
    So it would make more sense to name the files...

    web.config (the one in use)
    web.dev.config
    web.test.config
    web.prof.config

    and the last 3 would still be ignored?

  12. #12
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Add a folder somewhere appropriate--I usually keep another empty, non-compiling website project to contain this and other goodies like referenced libraries and DB scripts. Then just drop the configs in there and copy them out as appropriate. Operational goals are:

    a) You should always be able to check out everything you need to build and run a project out of source control.
    b) The actual project should be kept clean of extraneous stuff.

    I tend to use another project because I am lazy and I'd rather drag/drop stuff into the Solution Exporer and let VisaulSVN take care of keeping SVN in line, but alot of open source projects tend to have a tree structure where this stuff isn't necessarily part of the visual studio solution.

  13. #13
    SitePoint Guru pinch's Avatar
    Join Date
    Mar 2005
    Posts
    688
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Cool. Thanks for all the info.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •