Enum as Class Property
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);
Comments
-
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 almost 12 yearswhat 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 almost 12 yearsThat will not work AFAIK. Is there any reason why it should not be a 'normalized' item?
-
Refracted Paladin almost 12 yearssorry for the denseness but how do you mean 'normalized'? With an
int
backing it or some other way? -
leppie almost 12 yearsNormalized as in SQL terms,
TABLE Status (Id int PK, Name varchar(max))
. -
leppie almost 12 yearsAnd this will not blow up under LINQ2SQL?
-
Chris Shain almost 12 yearsEh, yeah probably would. Interesting to try though.
-
Refracted Paladin almost 12 yearsIt is interesting but for me error stating
an instance of string cannot be assigned to a member of type MyStatusID
-
Refracted Paladin almost 12 yearsI can look into it. It may be possible, I don't control DB setup so...:)
-
Chris Shain almost 12 yearsDid you change the signature of the
StatusID
property on the classStatus
? Your question shows it as aString
. -
Refracted Paladin almost 12 yearsYeah I did, I was trying to show how it was before I changed it.
-
comecme almost 12 yearsCan you cast a string to an enum?
-
Chris Shain almost 12 years@comecme I am guessing s.StatusID is an int.
-
comecme almost 12 yearsI don't think so. OP wants to replace
string StatusID
byMyStatusID StatusID
. He also states the database stores the statusid as varchar. -
Mare Infinitus almost 12 yearsdespite all that is possible, s.StatusID should be an int!
-
arserbin3 almost 12 yearsi 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 almost 12 yearsyour 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 becauseEnum.Parse
should just return anObject
type -
Refracted Paladin almost 12 yearsYour 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 almost 12 yearsIf 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 almost 12 yearsSee my Edit, does this mean I have to use your 2nd approach?
-
arserbin3 almost 12 yearscan 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