This question is asked on SO and this site often it looks like. “How do I do a dynamic enum?” Answers range from you shouldn’t to possible compile time solutions. Now my question is do I want a dynamic enum that is generated from look up tables in the DB, or do I want something else that is similar?
I have a solution using T4 at build time to generate enums from DB tables, that works fine. But now some of the look up tables have an ‘active’ flag on them. Does this mean they are not look up tables anymore? If that is changed I want to somehow regenerate my code without having to redeploy. These tables will not change often.
Currently the app when it wants to populate a dropdown or something will query the DB. But if the values mostly remain static, why go to the DB every time, hence the use of enums. It also has the added benefit of getting rid of magic strings and numbers.
Would static structs be better? Some sort of caching for the look up tables? Any advise welcome.
Don’t go to the DB every time. Go to the DB at process start; load into readonly dictionaries your lookup data, and call it good. Stuff changes underneath, you need to restart the app to re-grab those dictionaries.
Alternatively, look at actual resource cost of looking the data up every time, if your app isn’t significant enough for this to matter, just let it lookup the data everytime via join.
Cache expiration is a complex thing but two very simple techniques come to mind:
- Lock your lookup tables down to being updated by the app and those updates can signal a reinstantiation of your read-only lookup table dictionaries, this is so long as you don’t need to worry about people changing the lookup tables directly through management studio or otherwise.
- Using SQL server’s message broker triggered on updates to lookup tables to send a message to your running app which signals it to replace it’s readonly dictionaries with updated versions. This is presuming the updates will be manual SQL scripts
Alternatively use a proper cache like appfabric or memcached for these where you can have appropriate cache expiration if you need. This seems like overkill for what could really be served just fine by my initial suggestion, most systems have admins turn off their app when they go to update their DB directly anyway, and turn it back on only after DB updates are finished.
In summation:
No, you do not want dynamic enums, this goes against what an enum is even for
Enums are named consts. Remember that, consts. As soon as you want a group of key-value pairs you are starting down the path of hashtable/dictionary/associative-array or whatever word you wish to call them, that is precisely the purpose of such structures. Not the purpose of enums.
3
Whether something is an enum and whether you know it at compile time are 2 separate issues. In the case where you do always know the values at compile time (even though it changes over releases), and it happens to be convenient to have it as some kind of explicitly typed object in your object oriented language and as a table in the DB, then I think code generating the object from the DB (or anything DRY – generating a DB script via reflection, generating DB script and object generation from something else…) is O.K.
Whether you should model that as an enum is a separate issue. Enums aren’t very flexible when requirements change, so I would be wary.
You also say you don’t want to redeploy. That seems like the enemy of explicitness. If the changes to your “enums” (or whatever they turn out to be) happen more often then your releases, then you really don’t know the values at compile time. So you should get it from the DB, with or without caching based on the usual considerations.
5