Вопрос

I believe this is a common situation but couldn't find a satisfactory answer with Googling.

Question: Is there a pattern that addresses looking up enum values from the database?

Situation: I have been tasked with refactoring a Winforms app that is getting really heavy on memory usage. The main culprit is a "Constants" project - basically a bunch of Enum classes. Their purpose is to duplicate database lookup table values (see example below).

    public enum Status
    {
        None = -1,
        Active = 0,
        Completed = 1,
        Review = 2,
        Proceed = 3
    }

All of these enums have to be loaded in memory every single time the app loads. Is there a pattern that allows you to fix this problem, but also doesn't kill the database with queries?

Это было полезно?

Решение

While it's quite hard to believe that an assembly of enums could indeed be the main source of high memory usage (I don't even want to imagine the SIZE of that assembly), some possible solutions flow into mind:

  1. Exploring your memory-greedy enum assembly for things other than enums. Yes, it is a trivial advice, but it could prove the most reasonable after all.
  2. Merging your enum assembly with main project. While enums by themselves are hardly memory consuming, associated oversized assembly could well be all by itself (because of heavy usage of attributes, for instance).
  3. Implementing necessary values with a bunch of not-necessarily static classes, filled with a bunch of public static readonly int fields (not consts). Hardly will reduce memory usage if all of them are called at least once, but could lead to some reduction depending on user's actions. However, those pesky ints are harder to account for then enums.
  4. Implementing necessary values with cached singleton-ish pattern (perhaps there is a name for such a pattern, but I am not familiar with it). While obviously harder on memory on a per-instance basis, it allows (while depending on GC) to be put into life and snuffed out of it based on usage. Basically, it should be something like

    internal abstract class ErzatsEnumBase {
        protected static readonly ObjectCache Cache = MemoryCache.Default;
        protected ErzatsEnumBase ( string CacheKey, CacheItemPolicy CachePolicy ) {
            Cache.Add ( CacheKey, this, CachePolicy, null );
        }
    }
    public sealed class ErzatsEnum: ErzatsEnumBase {
        private static CacheItemPolicy policy = new CacheItemPolicy () {
            AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration,
            SlidingExpiration = new TimeSpan ( 0, 15, 0 )
        };
        private ErzatsEnum ( string CacheKey )
            : base ( CacheKey, policy ) {
        }
        public ErzatsEnum Instance1 {
            get {
                ErzatsEnum result = ErzatsEnumBase.Cache.Get ( "Instance1" );
                if ( result == null )
                   result = new ErzatsEnum ( "Instance1" );
                return result;
            }
        }
        public ErzatsEnum Instance2 {
            get {
                ErzatsEnum result = ErzatsEnumBase.Cache.Get ( "Instance2" );
                if ( result == null )
                   result = new ErzatsEnum ( "Instance2" );
                return result;
            }
        }
    }
    

Hope some of it proved useful :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top