Enum as Class Property

16,171

Solution 1

i believe what you're searching for is:

StatusID = (MyStatusID)Enum.Parse(typeof(MyStatusID), s.StatusID),

in .Net 4.0 there is also a Enum.TryParse(string, out enum) but that is not so useful inside your .Select()

Alternatively: albeit less efficient in most cases, you can keep the Status.StatusID as a string and add a readonly property StatusEnum that outputs the Enum value on the fly:

public MyStatusID StatusEnum {
    get {
        return (MyStatusID)Enum.Parse(typeof(MyStatusID), StatusID)
    }

    private set;
}

in .Net 4.0:
public MyStatusID StatusEnum {
    get {
        MyStatusID value;
        if(!Enum.TryParse(StatusID, out value)
          value = MyStatusID.Default; // default value, instead of Exception throwing

        return value;
    }

    private set;
}

this alternative re-parses the value everytime instance.StatusEnum is read, so I don't recommend it unless LINQ hates the first approach


Responding to your last EDIT:

The Enum.Parse() is translating to SQL fine in your example. The problem is in the switch statement where you're adding on a .Where() clause that has a comparison with an Enum. LINQ doesn't know how to turn an Enum == Enum into SQL but it does know to do it with C# objects. So the easiest solution is to ToList() them and do the comparison locally. Unfortunately, that means it's downloading rows of -all- Status types from the database and then filters them locally. If you have millions of records this may not be reasonable:

   public static IList<Status> GetAdminStatuses(NoaStatusID currentStatus = NoaStatusID.draft)
    {
        using (var context = MemberDataContext.Create())
        {
            List<Status> stat=context.tblAdminStatus
                   .Where(s => s.InactiveDate > DateTime.Now || s.InactiveDate == null)
                   .Select(s => new Status()
                     {
                       StatusID=NoaStatusID)Enum.Parse(typeof(NoaStatusID),s.StatusID),
                       StatusDescription=s.StatusDesc
                     })
                   .ToList();

            switch (currentStatus)
            {
                case NoaStatusID.draft:
                    stat=stat.Where(s => (s.StatusID == NoaStatusID.draft || s.StatusID == NoaStatusID.pending)).ToList();                                                     
                    break;
                case NoaStatusID.pending:
                    stat = stat.Where(s => (s.StatusID == NoaStatusID.accepted || s.StatusID ==NoaStatusID.declined || s.StatusID ==NoaStatusID.pending)).ToList();
                    break;                        
                case NoaStatusID.declined:
                    stat = stat.Where(s => (s.StatusID == NoaStatusID.draft || s.StatusID == NoaStatusID.pending || s.StatusID == NoaStatusID.declined)).ToList();
                    break;
                case NoaStatusID.accepted:
                    stat = stat.Where(s => (s.StatusID == NoaStatusID.mailed || s.StatusID == NoaStatusID.monitor || s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.accepted)).ToList();
                    break;
                case NoaStatusID.mailed:
                    stat = stat.Where(s => (s.StatusID == NoaStatusID.mailed || s.StatusID == NoaStatusID.monitor || s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.appeal)).ToList();
                    break;
                case NoaStatusID.monitor:
                case NoaStatusID.appeal:
                case NoaStatusID.close:
                    stat = stat.Where(s => (s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.appeal)).ToList();   
                    break;                    
            }


            return stat;
        }
    }

Solution 2

Isn't what you are looking for?

 Colors colorValue = (Colors) Enum.Parse(typeof(Colors), colorString);
Share:
16,171
Refracted Paladin
Author by

Refracted Paladin

My Philosophy

Updated on June 04, 2022

Comments

  • Refracted Paladin
    Refracted Paladin almost 2 years

    I have a class for something simple, Status, and it contains two properties. I want to use an Enum for one of the Properties(StatusID) so that I can eliminate a bunch of Magic Strings.

    My question is how I then work with it, for example: I have a Method that returns a List for binding in a dropdown box that looks like this -->

    public static IList<Status> GetAdminStatuses()
    {
      IQueryable<Status> stat=context.tblAdminStatus
           .Where(s => s.InactiveDate > DateTime.Now || s.InactiveDate == null)
           .Select(s => new Status()
           {
             StatusID=s.StatusID,
             StatusDescription=s.StatusDesc
           });
       return stat.ToList();
    }
    

    It obviously does not like my StatusID=s.StatusID part as the DB stores it as a varchar. Am I missing something simple here or have I stumbled into noob territory and should not be doing it this way?

    For reference here is the Class and Enum:

    public class Status
    {
      public string StatusID {get; set;}
      public string StatusDescription {get; set;}
    }
    
    public enum MyStatusID
    {
      draft, pending, declined, accepted, close 
    }
    

    EDIT

    So taking the advice here I was able to get my method to compile however at runtime I get the following --> Method 'System.Object Parse(System.Type, System.String)' has no supported translation to SQL.

    Thoughts?


    EDIT - Method in it's entirety by request, thanks (NOTE that NoaStatusID == MyStatusID)

       public static IList<Status> GetAdminStatuses(NoaStatusID currentStatus = NoaStatusID.draft)
        {
            using (var context = MemberDataContext.Create())
            {
                IQueryable<Status> stat=context.tblAdminStatus
                       .Where(s => s.InactiveDate > DateTime.Now || s.InactiveDate == null)
                       .Select(s => new Status()
                         {
                           StatusID=NoaStatusID)Enum.Parse(typeof(NoaStatusID),s.StatusID),
                           StatusDescription=s.StatusDesc
                         });
    
                switch (currentStatus)
                {
                    case NoaStatusID.draft:
                        stat=stat.Where(s => (s.StatusID == NoaStatusID.draft || s.StatusID == NoaStatusID.pending));                                                     
                        break;
                    case NoaStatusID.pending:
                        stat = stat.Where(s => (s.StatusID == NoaStatusID.accepted || s.StatusID ==NoaStatusID.declined || s.StatusID ==NoaStatusID.pending));
                        break;                        
                    case NoaStatusID.declined:
                        stat = stat.Where(s => (s.StatusID == NoaStatusID.draft || s.StatusID == NoaStatusID.pending || s.StatusID == NoaStatusID.declined));
                        break;
                    case NoaStatusID.accepted:
                        stat = stat.Where(s => (s.StatusID == NoaStatusID.mailed || s.StatusID == NoaStatusID.monitor || s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.accepted));
                        break;
                    case NoaStatusID.mailed:
                        stat = stat.Where(s => (s.StatusID == NoaStatusID.mailed || s.StatusID == NoaStatusID.monitor || s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.appeal));
                        break;
                    case NoaStatusID.monitor:
                    case NoaStatusID.appeal:
                    case NoaStatusID.close:
                        stat = stat.Where(s => (s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.appeal));   
                        break;                    
                }
    
    
                return stat.ToList();
            }
        }
    
  • Refracted Paladin
    Refracted Paladin almost 12 years
    what if the enum is literally a string representation of what I want. e.g. MyStatusID.draft == "draft" or are you saying I'd be better off switching my DB ID column to int then in this instance?
  • leppie
    leppie almost 12 years
    That will not work AFAIK. Is there any reason why it should not be a 'normalized' item?
  • Refracted Paladin
    Refracted Paladin almost 12 years
    sorry for the denseness but how do you mean 'normalized'? With an int backing it or some other way?
  • leppie
    leppie almost 12 years
    Normalized as in SQL terms, TABLE Status (Id int PK, Name varchar(max)).
  • leppie
    leppie almost 12 years
    And this will not blow up under LINQ2SQL?
  • Chris Shain
    Chris Shain almost 12 years
    Eh, yeah probably would. Interesting to try though.
  • Refracted Paladin
    Refracted Paladin almost 12 years
    It is interesting but for me error stating an instance of string cannot be assigned to a member of type MyStatusID
  • Refracted Paladin
    Refracted Paladin almost 12 years
    I can look into it. It may be possible, I don't control DB setup so...:)
  • Chris Shain
    Chris Shain almost 12 years
    Did you change the signature of the StatusID property on the class Status? Your question shows it as a String.
  • Refracted Paladin
    Refracted Paladin almost 12 years
    Yeah I did, I was trying to show how it was before I changed it.
  • comecme
    comecme almost 12 years
    Can you cast a string to an enum?
  • Chris Shain
    Chris Shain almost 12 years
    @comecme I am guessing s.StatusID is an int.
  • comecme
    comecme almost 12 years
    I don't think so. OP wants to replace string StatusID by MyStatusID StatusID. He also states the database stores the statusid as varchar.
  • Mare Infinitus
    Mare Infinitus almost 12 years
    despite all that is possible, s.StatusID should be an int!
  • arserbin3
    arserbin3 almost 12 years
    i agree with leppie, ideally your database column should be an int foreign keyed to a StatusType table. It makes indexing and querying faster and saves space. But not always possible for legacy and in-production systems
  • arserbin3
    arserbin3 almost 12 years
    your third of four answers is the correct one (as it is a copy of my already supplied answer). However i believe it would need a (MyStatusID) casting because Enum.Parse should just return an Object type
  • Refracted Paladin
    Refracted Paladin almost 12 years
    Your first approach seems to work. Thanks very much, I will see what I can do about getting that column switched to an int but I am glad to have found a way to make it work anyway.
  • Refracted Paladin
    Refracted Paladin almost 12 years
    If I would have been paying attention this is works as well and is the same as a couple of the other answers. THanks
  • Refracted Paladin
    Refracted Paladin almost 12 years
    See my Edit, does this mean I have to use your 2nd approach?
  • arserbin3
    arserbin3 almost 12 years
    can you post your code under the edit. I just attempted it myself locally and do not get the System.NotSupportedException exception - works fine for me. Using .Net4.0