This is a migrated thread and some comments may be shown as answers.

Static class value constant

3 Answers 43 Views
Development (API, general questions)
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Vitaliy
Top achievements
Rank 1
Vitaliy asked on 21 Nov 2014, 02:24 PM

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?

3 Answers, 1 is accepted

Sort by
0
Kaloyan Nikolov
Telerik team
answered on 26 Nov 2014, 09:45 AM
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.
 
0
Vitaliy
Top achievements
Rank 1
answered on 26 Nov 2014, 05:12 PM
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?
0
Accepted
Kaloyan Nikolov
Telerik team
answered on 27 Nov 2014, 02:49 PM
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.
 
Tags
Development (API, general questions)
Asked by
Vitaliy
Top achievements
Rank 1
Answers by
Kaloyan Nikolov
Telerik team
Vitaliy
Top achievements
Rank 1
Share this question
or