作为枚举类属性 [英] Enum as Class Property

查看:202
本文介绍了作为枚举类属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一类简单的东西,状态,它包含两个属性。我想用一个枚举的属性(StatusID)中的一个,这样我可以消灭一堆魔字符串。

我的问题是,再怎么我使用它,比如:我有一个方法,该方法返回一个列表在一个下拉框,看起来像这样绑定 - >

 公共静态的IList<状态> GetAdminStatuses()
{
  IQueryable的<状态> STAT = context.tblAdminStatus
       。凡(S => s.InactiveDate> DateTime.Now || s.InactiveDate == NULL)
       。选择(S =>新建状态()
       {
         StatusID = s.StatusID,
         状态说明= s.StatusDesc
       });
   返回stat.ToList();
}
 

这显然不喜欢我的 StatusID = s.StatusID 部分为DB将它存储为VARCHAR。我失去了一些简单的在这里还是有我偶然到小白的领土,不应该做这种方式?

有关参考这里是类和枚举:

 公共类状态
{
  公共字符串StatusID {获得;组;}
  公共字符串状态说明{获得;组;}
}

公共枚举MyStatusID
{
  草案,以待,拒绝,接受,关闭
}
 


修改

因此​​,采取的意见在这里我能得到我的方法但是编译在运行时我得到以下 - > 法System.Object的解析(System.Type的,System.String)有不支持转换为SQL。

思考?


编辑 - 它的方法是全部按要求,谢谢(请注意,NoaStatusID == MyStatusID)

 公共静态的IList<状态> GetAdminStatuses(NoaStatusID currentStatus = NoaStatusID.draft)
    {
        使用(VAR上下文= MemberDataContext.Create())
        {
            IQueryable的<状态> STAT = context.tblAdminStatus
                   。凡(S => s.InactiveDate> DateTime.Now || s.InactiveDate == NULL)
                   。选择(S =>新建状态()
                     {
                       StatusID = NoaStatusID)Enum.Parse(typeof运算(NoaStatusID),​​s.StatusID)
                       状态说明= s.StatusDesc
                     });

            开关(currentStatus)
            {
                案例NoaStatusID.draft:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.draft || s.StatusID == NoaStatusID.pending));
                    打破;
                案例NoaStatusID.pending:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.accepted || s.StatusID == NoaStatusID.declined || s.StatusID == NoaStatusID.pending));
                    打破;
                案例NoaStatusID.declined:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.draft || s.StatusID == NoaStatusID.pending || s.StatusID == NoaStatusID.declined));
                    打破;
                案例NoaStatusID.accepted:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.mailed || s.StatusID == NoaStatusID.monitor || s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.accepted) );
                    打破;
                案例NoaStatusID.mailed:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.mailed || s.StatusID == NoaStatusID.monitor || s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.appeal) );
                    打破;
                案例NoaStatusID.monitor:
                案例NoaStatusID.appeal:
                案例NoaStatusID.close:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.appeal));
                    打破;
            }


            返回stat.ToList();
        }
    }
 

解决方案

我相信你正在寻找的是:

  StatusID =(MyStatusID)Enum.Parse(typeof运算(MyStatusID),​​s.StatusID)
 

在.NET 4.0中也有一个 Enum.TryParse(字符串,出枚举)但是这不是你的。选择里面非常有用( )

或者 尽管在大多数情况下效率不高,你可以保持 Status.StatusID 作为一个字符串,并添加只读属性 StatusEnum 的飞输出枚举值:

 公共MyStatusID StatusEnum {
    得到 {
        返程(MyStatusID)Enum.Parse(typeof运算(MyStatusID),​​StatusID)
    }

    私定;
}

在.NET 4.0中:
公共MyStatusID StatusEnum {
    得到 {
        MyStatusID值;
        如果(!Enum.TryParse(StatusID,超时值)
          值= MyStatusID.Default; //默认值,而不是异常投掷

        返回值;
    }

    私定;
}
 

这种替代重新解析值每次instance.StatusEnum被读取,所以我不建议这样做,除非LINQ恨第一种方法


在回答你的最后编辑:

在Enum.Parse()被翻译成SQL罚款,你的榜样。问题出在哪里,你要添加一个。凡()子句具有与枚举。 LINQ不知道如何把一个枚举==枚举成SQL,但它的确实知道用C#对象做到这一点。因此最简单的解决办法就是了ToList()他们,并做局部的比较。不幸的是,这意味着它的下载行从数据库中-all-状态类型,然后在本地过滤它们。如果你有百万条记录这未必是合理的:

 公共静态的IList<状态> GetAdminStatuses(NoaStatusID currentStatus = NoaStatusID.draft)
    {
        使用(VAR上下文= MemberDataContext.Create())
        {
            名单<状态> STAT = context.tblAdminStatus
                   。凡(S => s.InactiveDate> DateTime.Now || s.InactiveDate == NULL)
                   。选择(S =>新建状态()
                     {
                       StatusID = NoaStatusID)Enum.Parse(typeof运算(NoaStatusID),​​s.StatusID)
                       状态说明= s.StatusDesc
                     })
                   .ToList();

            开关(currentStatus)
            {
                案例NoaStatusID.draft:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.draft || s.StatusID == NoaStatusID.pending))了ToList()。
                    打破;
                案例NoaStatusID.pending:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.accepted || s.StatusID == NoaStatusID.declined || s.StatusID == NoaStatusID.pending))了ToList()。
                    打破;
                案例NoaStatusID.declined:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.draft || s.StatusID == NoaStatusID.pending || s.StatusID == NoaStatusID.declined))了ToList()。
                    打破;
                案例NoaStatusID.accepted:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.mailed || s.StatusID == NoaStatusID.monitor || s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.accepted) ).ToList();
                    打破;
                案例NoaStatusID.mailed:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.mailed || s.StatusID == NoaStatusID.monitor || s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.appeal) ).ToList();
                    打破;
                案例NoaStatusID.monitor:
                案例NoaStatusID.appeal:
                案例NoaStatusID.close:
                    STAT = stat.Where(S =>(s.StatusID == NoaStatusID.close || s.StatusID == NoaStatusID.appeal))了ToList()。
                    打破;
            }


            返回统计;
        }
    }
 

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();
        }
    }

解决方案

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;
        }
    }

这篇关于作为枚举类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆