Best way to store lookup variables?

Discussion in 'ASP .Net' started by john_c, Feb 20, 2007.

  1. john_c

    john_c Guest

    I'd like to store information for roles in Session variables. RoleA
    has a specific set of values, RoleB has a specific set and so one.
    When I access values for RoleA, it looks like this:

    Session[Utils.RoleA_MBcount] = "30"
    Session[Utils.RoleA_BandwidthLimit] = "1000"
    Session[Utils.RoleA_FeatureBcountLimit] = "5"
    Session[Utils.RoleA_FeatureCcountLimit] = "10"

    and similar for the other roles. Those values are initially loaded
    from a database. Each role is actually a purchased plan. Similar to
    various hosting plans that give you more the more you pay. Once the
    roles are initialized into Session variables, I just access the
    Session variable to check user limits.

    Each of the above properties in Utils is a static string reference.
    They're just nice ways to give me intellisense and avoid hard coding
    strings everywhere. The problem is that I'll have to hit the Utils.cs
    file everytime I want to use these lookup values. If there are four
    roles and each one has 10 properties that could be a lot of hits
    (especially with more roles) depending on how grouped the lookups are
    through out the app.

    Is this a concern or is there a better way?

    Thanks,
    John
     
    john_c, Feb 20, 2007
    #1
    1. Advertising

  2. john_c

    Mark Rae Guest

    "john_c" <> wrote in message
    news:...

    > The problem is that I'll have to hit the Utils.cs file everytime I want to
    > use these lookup values.


    In fact, you don't... The Utils.cs file, like all your other C# code files,
    is compiled up into your web app's DLL when you rebuild the app, which is
    loaded into memory when the app starts...

    > Is this a concern or is there a better way?


    I wouldn't have thought it was a concern...

    As for a better way, that's a little difficult to say... There are certainly
    other ways - you could use one of the Collection objects (e.g. ArrayList) or
    Generics objects (e.g. Dictionary) if you're using ASP.NET v2, or you could
    hold each element separately in Session - if there are any performance
    differences, we're probably looking at nanoseconds...
     
    Mark Rae, Feb 20, 2007
    #2
    1. Advertising

  3. john_c

    john_c Guest

    On Feb 20, 3:34 pm, "Mark Rae" <> wrote:
    > "john_c" <> wrote in message
    >
    > news:...
    >
    > > The problem is that I'll have to hit the Utils.cs file everytime I want to
    > > use these lookup values.

    >
    > In fact, you don't... The Utils.cs file, like all your other C# code files,
    > is compiled up into your web app's DLL when you rebuild the app, which is
    > loaded into memory when the app starts...


    You're right Mark. Thanks. I guess the "static" accessor threw me
    off. Do these static properties stay in memory for the length of the
    user session or app session?

    >
    > > Is this a concern or is there a better way?

    >
    > I wouldn't have thought it was a concern...
    >
    > As for a better way, that's a little difficult to say... There are certainly
    > other ways - you could use one of the Collection objects (e.g. ArrayList) or
    > Generics objects (e.g. Dictionary) if you're using ASP.NET v2, or you could
    > hold each element separately in Session - if there are any performance
    > differences, we're probably looking at nanoseconds...


    I am using ASP.NET 2.0. A collection could be used but I think a
    better way is to group each role by static class in the Utils class,
    which is also static. This just gives a nice intellisense layout. So
    you would have

    Session[Utils.Roles.RoleA.MBcount]
    Session[Utils.Roles.RoleA.BandwidthLimit]
    Session[Utils.Roles.RoleA.FeatureBcountLimit]
    Session[Utils.Roles.RoleA.FeatureCcountLimit]
     
    john_c, Feb 20, 2007
    #3
  4. john_c

    john_c Guest

    Also, there will be corresponding Application cache for each plan.
    The user Session values are compared against it. This means the
    database only needs to be hit when the app loads and for each new user
    (session).
     
    john_c, Feb 20, 2007
    #4
  5. John,
    Do you really need it as a session variable? Will it be the same
    values for each session? If so then you're going to end up with a lot of
    useless memory usage. You could put the values into the cache object. You
    could do a check every so often, such as when a request starts, and check to
    see if the cache is empty. If so then load the object/array/etc. through
    some function and put it into the cache. This would give you a good bit of
    control as well since you could determine how much time should occur to
    cause the items to fall out of the cache.

    --

    Hope this helps,
    Mark Fitzpatrick
    Former Microsoft FrontPage MVP 199?-2006

    "john_c" <> wrote in message
    news:...
    > I'd like to store information for roles in Session variables. RoleA
    > has a specific set of values, RoleB has a specific set and so one.
    > When I access values for RoleA, it looks like this:
    >
    > Session[Utils.RoleA_MBcount] = "30"
    > Session[Utils.RoleA_BandwidthLimit] = "1000"
    > Session[Utils.RoleA_FeatureBcountLimit] = "5"
    > Session[Utils.RoleA_FeatureCcountLimit] = "10"
    >
    > and similar for the other roles. Those values are initially loaded
    > from a database. Each role is actually a purchased plan. Similar to
    > various hosting plans that give you more the more you pay. Once the
    > roles are initialized into Session variables, I just access the
    > Session variable to check user limits.
    >
    > Each of the above properties in Utils is a static string reference.
    > They're just nice ways to give me intellisense and avoid hard coding
    > strings everywhere. The problem is that I'll have to hit the Utils.cs
    > file everytime I want to use these lookup values. If there are four
    > roles and each one has 10 properties that could be a lot of hits
    > (especially with more roles) depending on how grouped the lookups are
    > through out the app.
    >
    > Is this a concern or is there a better way?
    >
    > Thanks,
    > John
    >
     
    Mark Fitzpatrick, Feb 21, 2007
    #5
  6. Hi there John and Mark,

    You could go even further and create a base page class with properties you
    want. this approach gives you possiblity to get already casted and defaulted
    values with great support from intelli sense:

    -- begin rolebasepage.cs code --

    public class RoleBasePage : System.Web.UI.Page
    {
    public RoleBasePage() : base()
    {
    }

    private RoleAProperties roleA;
    public RoleAProperties RoleA
    {
    get
    {
    if (this.roleA == null)
    this.roleA = new RoleAProperties(Session);
    return this.roleA;
    }
    }

    public sealed class RoleAProperties
    {
    private System.Web.SessionState.HttpSessionState session;

    public RoleAProperties(System.Web.SessionState.HttpSessionState session)
    {
    if (session == null)
    throw new NullReferenceException("session");
    this.session = session;
    }

    public int MBCount
    {
    get
    {
    object value = this.session["RoleAMBCount"];
    return value == null ? 0 /* default value */ : (int) value;
    }
    set
    {
    this.session["RoleAMBCount"] = value;
    }
    }
    }
    }
    -- end rolebasepage.cs --

    -- begin any aspx page code behind --
    public partial class MyAnyPage : RoleBasePage
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    if (RoleA.MBCount < 10)
    {
    // do something -
    // not enough MB allowance to approve the invoice
    // or whatsoever
    }
    }
    }

    -- end any aspx page code behind --

    Milosz


    "Mark Rae" wrote:

    > "john_c" <> wrote in message
    > news:...
    >
    > > The problem is that I'll have to hit the Utils.cs file everytime I want to
    > > use these lookup values.

    >
    > In fact, you don't... The Utils.cs file, like all your other C# code files,
    > is compiled up into your web app's DLL when you rebuild the app, which is
    > loaded into memory when the app starts...
    >
    > > Is this a concern or is there a better way?

    >
    > I wouldn't have thought it was a concern...
    >
    > As for a better way, that's a little difficult to say... There are certainly
    > other ways - you could use one of the Collection objects (e.g. ArrayList) or
    > Generics objects (e.g. Dictionary) if you're using ASP.NET v2, or you could
    > hold each element separately in Session - if there are any performance
    > differences, we're probably looking at nanoseconds...
    >
    >
    >
     
    =?Utf-8?B?TWlsb3N6IFNrYWxlY2tpIFtNQ0FEXQ==?=, Feb 21, 2007
    #6
  7. john_c

    Mark Rae Guest

    "john_c" <> wrote in message
    news:...

    > You're right Mark. Thanks. I guess the "static" accessor threw me
    > off. Do these static properties stay in memory for the length of the
    > user session or app session?


    See the other replies - you need to be *very* careful with statics in
    ASP.NET... They can very easily become common across all sessions which,
    depending on what they're used for, could be the absolute last thing you
    want...
     
    Mark Rae, Feb 21, 2007
    #7
  8. john_c

    john_c Guest

    Hi Milosz,

    I like this approach but could you do it without inheritence?
     
    john_c, Feb 21, 2007
    #8
  9. john_c

    john_c Guest

    No, it doesn't need to be in a session variable. I just need to load
    the cache with values for each plan. Then I can check the User object
    to find out which role/plan the user is in. From there I have the
    values for the plan associated with the user in the Cache and can take
    action to display something or not. But how could I cleanly
    associate "yes, I know the user's role" with "in the Cache are all of
    the values for that role/plan". I need some sort of constuct that
    allows me to put those two things together initially. Then when I
    need to check the MegaBytes of space a user has, I can just say
    User.MBcount or something similar.

    Thanks.

    On Feb 20, 4:22 pm, "Mark Fitzpatrick" <> wrote:
    > John,
    > Do you really need it as a session variable? Will it be the same
    > values for each session? If so then you're going to end up with a lot of
    > useless memory usage. You could put the values into the cache object. You
    > could do a check every so often, such as when a request starts, and check to
    > see if the cache is empty. If so then load the object/array/etc. through
    > some function and put it into the cache. This would give you a good bit of
    > control as well since you could determine how much time should occur to
    > cause the items to fall out of the cache.
     
    john_c, Feb 21, 2007
    #9
  10. Yes, but ypu need to code quite a lot and you need to spend some time to
    familirize youself with custom proofile providers. i'll perape a simple
    example but tomorrow (wed late afternoon CET)

    Regards

    --
    Milosz


    "john_c" wrote:

    > Hi Milosz,
    >
    > I like this approach but could you do it without inheritence?
    >
    >
     
    =?Utf-8?B?TWlsb3N6IFNrYWxlY2tpIFtNQ0FEXQ==?=, Feb 21, 2007
    #10
  11. john_c

    john_c Guest

    On Feb 20, 6:26 pm, Milosz Skalecki [MCAD] <>
    wrote:
    > Yes, but ypu need to code quite a lot and you need to spend some time to
    > familirize youself with custom proofile providers. i'll perape a simple
    > example but tomorrow (wed late afternoon CET)


    Hi Milosz. I'll be looking forward to it.
     
    john_c, Feb 21, 2007
    #11
  12. I know i know,

    Here's the custom profileprovider class that should be placed in app_code
    folder. you also need to amend web.config (that's actual place where you
    define all properties)

    -- begin MyProfileProvider.cs c# code --


    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    /// <summary>
    /// Summary description for MyProfileProvider
    /// </summary>
    public class MyProfileProvider : System.Web.Profile.ProfileProvider
    {
    public MyProfileProvider()
    : base()
    {
    }

    public override int
    DeleteInactiveProfiles(System.Web.Profile.ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
    {
    throw new Exception("The method or operation is not implemented.");
    }

    public override int DeleteProfiles(string[] usernames)
    {
    throw new Exception("The method or operation is not implemented.");
    }

    public override int DeleteProfiles(System.Web.Profile.ProfileInfoCollection
    profiles)
    {
    throw new Exception("The method or operation is not implemented.");
    }

    public override System.Web.Profile.ProfileInfoCollection
    FindInactiveProfilesByUserName(System.Web. Profile.ProfileAuthenticationOption
    authenticationOption, string usernameToMatch,
    DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int
    totalRecords)
    {
    throw new Exception("The method or operation is not implemented.");
    }

    public override System.Web.Profile.ProfileInfoCollection
    FindProfilesByUserName(System.Web.Profile.ProfileAuthenticationOption
    authenticationOption, string usernameToMatch, int pageIndex, int pageSize,
    out int totalRecords)
    {
    throw new Exception("The method or operation is not implemented.");
    }

    public override System.Web.Profile.ProfileInfoCollection
    GetAllInactiveProfiles(System.Web.Profile.ProfileAuthenticationOption
    authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int
    pageSize, out int totalRecords)
    {
    throw new Exception("The method or operation is not implemented.");
    }

    public override System.Web.Profile.ProfileInfoCollection
    GetAllProfiles(System.Web.Profile.ProfileAuthenticationOption
    authenticationOption, int pageIndex, int pageSize, out int totalRecords)
    {
    throw new Exception("The method or operation is not implemented.");
    }

    public override int
    GetNumberOfInactiveProfiles(System.Web.Profile.ProfileAuthenticationOption
    authenticationOption, DateTime userInactiveSinceDate)
    {
    throw new Exception("The method or operation is not implemented.");
    }

    // ApplicationName property is used only if profile data
    // depends on application instance - i.e. in case there are many
    // applications and the data
    public override string ApplicationName
    {
    get
    {
    return String.Empty;
    }
    set
    {
    }
    }

    public override SettingsPropertyValueCollection GetPropertyValues(
    SettingsContext context, SettingsPropertyCollection collection)
    {

    System.Web.SessionState.HttpSessionState session =
    HttpContext.Current.Session;

    SettingsPropertyValueCollection settings =
    new SettingsPropertyValueCollection();

    foreach (SettingsProperty property in collection)
    {
    SettingsPropertyValue settingsPropertyValue =
    new SettingsPropertyValue(property);

    // remember this logic would only work if session
    // keys are the same as properties name including grouping

    object value = session[property.Name];
    // set value for non null PropertyValues only in
    // order to force default value defined in the web.config
    if (value != null)
    {
    settingsPropertyValue.PropertyValue = value;
    settingsPropertyValue.IsDirty = false;
    settingsPropertyValue.SerializedValue = value;
    }

    settings.Add(settingsPropertyValue);
    }

    return settings;
    }

    public override void SetPropertyValues(SettingsContext context,
    SettingsPropertyValueCollection collection)
    {
    System.Web.SessionState.HttpSessionState session =
    HttpContext.Current.Session;

    if (session == null)
    return;

    foreach (SettingsPropertyValue settingsPropertyValue in collection)
    {
    // i assume every sigle property defined for profile is stored in session,
    // other wise you have to update session for selected items only

    if (settingsPropertyValue.IsDirty)
    {
    if (settingsPropertyValue.PropertyValue == null)
    {
    session.Remove(settingsPropertyValue.Name);
    }
    else
    {
    session[settingsPropertyValue.Name] =
    settingsPropertyValue.PropertyValue;
    }
    }
    }

    }
    }

    -- end code --

    -- web.config changes--

    <anonymousIdentification enabled="true"/>
    <profile enabled="true" defaultProvider="MyProfileProvider"
    automaticSaveEnabled="true">
    <providers>
    <add name="MyProfileProvider" type="MyProfileProvider"/>
    </providers>
    <properties>
    <group name="RoleA">
    <add name="MBCount" type="System.Int32" defaultValue="0" readOnly="false"
    allowAnonymous="true"/>
    </group>
    </properties>
    </profile>

    -- end web.config changes --


    -- how to use it on the page --

    <asp:Button runat="server" ID="btn" Text="Postback!" />

    <script runat="server">

    protected void Page_Load(object sender, EventArgs e)
    {
    // you have to call Profile.Save()
    // everytime you change properties to force values
    // to be updated in underlying data storage which
    // on our case is session. the reason for that is
    // very simple - profileprovider.setpropertyvalues
    // is called at the final stage of page execution
    // after session state is serialized and destroyed
    // therefore is not acessible. remember save should
    // be called onnce per execution i.e. after you set
    // all properties you want.

    if (IsPostBack)
    {
    Profile.RoleA.MBCount++;
    Profile.Save();
    }
    else
    {
    Profile.RoleA.MBCount = 3;
    Profile.Save();
    }

    Response.Write(Profile.RoleA.MBCount);
    }
    </script>

    --
    Milosz


    "john_c" wrote:

    > On Feb 20, 6:26 pm, Milosz Skalecki [MCAD] <>
    > wrote:
    > > Yes, but ypu need to code quite a lot and you need to spend some time to
    > > familirize youself with custom proofile providers. i'll perape a simple
    > > example but tomorrow (wed late afternoon CET)

    >
    > Hi Milosz. I'll be looking forward to it.
    >
    >
     
    =?Utf-8?B?TWlsb3N6IFNrYWxlY2tpIFtNQ0FEXQ==?=, Feb 22, 2007
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Max
    Replies:
    2
    Views:
    464
  2. Tarun Mistry

    Best way to store a time?

    Tarun Mistry, Feb 22, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    336
    Karl Seguin [MVP]
    Feb 22, 2006
  3. Replies:
    13
    Views:
    11,026
  4. kelvSYC

    Best way to do a lookup tree

    kelvSYC, Mar 6, 2006, in forum: C++
    Replies:
    3
    Views:
    337
  5. Vajra
    Replies:
    6
    Views:
    1,166
    Chris ( Val )
    Oct 8, 2007
Loading...

Share This Page