Static class value constant

4 posts, 1 answers
  1. Vitaliy
    Vitaliy avatar
    36 posts
    Member since:
    Dec 2008

    Posted 21 Nov 2014 Link to this post

    Hello

    I need for two things:
    1. Load a full list of some class values
    2. Use mnemonics constants of some (or all) class values.

    For example, I want to check something like:

    if(mainContractor.ApprovalStatus == ContractorApprovalStatus.NotApproved)
        throw new Exception(....

    I code the constants like this:
    public static ContractorApprovalStatus NotApproved{
        get { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == 0); }
    }
     
    public static ContractorApprovalStatus Approved{
        get { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == 1); }
    }
     
    public static ContractorApprovalStatus RMCApproved{
        get { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == 2); }
    }
     
    public static ContractorApprovalStatus ApprovalNotRequired{
        get { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == 3); }
    }
     
    public static ContractorApprovalStatus ApprovalRefused{
        get { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == 4); }
    }
     
    public static ContractorApprovalStatus ApprovalInProgress{
        get { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == 5); }
    }
     
    public static ContractorApprovalStatus InvitationIssued{
        get { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == 6); }
    }
     
    public static ContractorApprovalStatus BlockSpecificApproved{
        get { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == 7); }
    }
     
    public static ContractorApprovalStatus ApplicationPackSent{
        get { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == 8); }
    }

    Well, numeric constants is a bad practice, but I generate the code automatically with a query:
    SELECT 'public static ContractorApprovalStatus '+ replace(StatusName, ' ', '') +'{ get  { return PMSDataSession.Context.ContractorApprovalStatus.FirstOrDefault(s => s.ID == '+ rtrim(CAST(ContractorApprovalStatus_id AS CHAR)) +');}}'
    FROM ContractorApprovalStatus
    ORDER BY ContractorApprovalStatus_id
    ;)

    It looks fine to me, but I don't like so an SQL query is running every time when I use a 'constant' ContractorApprovalStatus.NotApproved.
    The table is absolutely static. probably I cal load all the table in a cache? (it is a shame I never used it)

    What would be the best practice from the optimization POW?

  2. Kaloyan Nikolov
    Admin
    Kaloyan Nikolov avatar
    118 posts

    Posted 26 Nov 2014 Link to this post

    Hi Vitaliy,

    I would suggest you to use an enum mapped directly to your foreign key instead of the loading the Status entity in a navigational property. To do so you will need to generate once the enum with s similar query you already use to generate your static constants. The key ingredient is that the underlining enum member values should map the ids from your static table. This article describes how to utilize the custom enum type in your model. The Enum would look like this:
    public enum ContractorApprovalStatus
    {
      NotApproved = 0,
      Approved = 1,
      ...
    }

    Once you have mapped your model in this way you can use the enum in LINQ queries or in IF statements like the one you mentioned.

    Performance wise this will optimize your queries because you will not need to load the Status entities at all. You can keep the records in the table only to ensure the data integrity. So you should update the enum if you add a new record in the static table. 

    I hope this helps. 

    Regards,
    Kaloyan Nikolov
    Telerik
     
    OpenAccess ORM is now Telerik Data Access. For more information on the new names, please, check out the Telerik Product Map.
     
  3. DevCraft banner
  4. Vitaliy
    Vitaliy avatar
    36 posts
    Member since:
    Dec 2008

    Posted 26 Nov 2014 in reply to Kaloyan Nikolov Link to this post

    Sounds like: the better practice to use State Patter do not use state pattern. :-)

    Okay, the question was like how to easy load a  a number of static persistent objects in a common 'cross contexts'  list?
  5. Answer
    Kaloyan Nikolov
    Admin
    Kaloyan Nikolov avatar
    118 posts

    Posted 27 Nov 2014 Link to this post

    Hi,

    Then I would suggest you to load all records from the table with a single query, detach them from the context that have loaded them. You can use the loaded collection in another context instances by calling context.CreateAttachedCopy() upfront or to use the list to feed the static properties like in your example the code would look like this:
    public static class StatusConsts
    {
        private static IList<ContractorApprovalStatus> allStatuses;
     
        private static ContractorApprovalStatus GetStatus(int id)
        {
            if (allStatuses == null)
            {
                using (var dbContext = new EntitiesModel1())
                {
                    var statuses = dbContext.ContractorApprovalStatus.ToList();
                     
                    //detaches the entities from the current context so it can be
                    //freed correctly and allow to use them in other contexts
                    allStatuses = dbContext.CreateDetachedCopy(statuses);
                }  
            }
     
            return allStatuses.FirstOrDefault(x => x.Id == id);
        }
    }
     
    private static ContractorApprovalStatus _apporved;
    public static ContractorApprovalStatus Approved
    {
        get
        {
            if(_apporved == null)
                _apporved = GetStatus(1);
            return _apporved
        }
    }

    You can see here that all properties will be initialized in a single query and the separation by Id will be done in memory. 

    Please let me know weather this covers your scenario. 

    Regards,
    Kaloyan Nikolov
    Telerik
     
    OpenAccess ORM is now Telerik Data Access. For more information on the new names, please, check out the Telerik Product Map.
     
Back to Top