InvalidCastException,从ASP.NET MVC中的SqlDataReader获取枚举值

时间:2016-10-16 07:09:28

标签: c# model-view-controller enums casting

我在运行时使用以下代码获得System.InvalidCastException

inf.Country = (Country)(int)rdr["Country"];

模特课:

public class BasicInfo
{
    .....
    public Gender Gender { get; set; }
    public Country Country { get; set; }
}

public enum Gender
{
    Male,
    Female
}

public enum Country
{
    Australia,
    Bangladesh,
    England,
    France,
    Usa
}

DbConnect class:该方法返回实体列表,它将通过控制器的视图。

usp_GetAllStudentData是一个返回记录列表的存储过程。

public List<BasicInfo> SelectStudent()
{
    ConnectionString();//Contain Connection string
    List<BasicInfo> entities = new List<BasicInfo>();

    SqlCommand cmd = new SqlCommand("usp_GetAllStudentData", conn);
    cmd.CommandType = CommandType.StoredProcedure;

    conn.Open();

    SqlDataReader rdr = cmd.ExecuteReader();
    while(rdr.Read())
    {
        BasicInfo inf = new BasicInfo();
        inf.FirstName = (string)rdr["FirstName"];
        .....//other required value are assigned to class members.
        //inf.Gender = (Gender)(int)rdr["Gender"];
        inf.Country = (Country)(int)rdr["Country"];  // Getting run time exception here 

        entities.Add(inf);
    }

    return entities;
}

How the data is stored in the database

你们能告诉我什么是投射枚举值的最佳方法吗?

或者让我知道是否有其他方法可以解决此问题。

Table Design

2 个答案:

答案 0 :(得分:1)

如果您的数据库字段包含NULL值,那么代码的结果就是无效的转换异常

例如

 object x = DbNull.Value;          // A null value on the db is represented by DbNull.Value
 inf.Country = (Country)(int)x;    // Gives the Invalid Cast Exception

如何修复取决于您想要使用空值做什么。如果您不允许国家/地区使用空值,则应修改接受无效输入的代码并阻止这些输入(并且不要忘记将“国家/地区”字段设置为“不允许数据库表上的NULL值”)

如果您接受空值,我建议您在国家/地区添加另一个条目

public enum Country
{
  Australia = 0,
  Bangladesh,
  England,
  France,
  Usa,
  // <=== new countries should be added here....
  Undefined = 9999
}

并将您的阅读代码更改为

int ordinal = rdr.GetOrdinal("Country");
inf.Country = rdr.IsDBNull(ordinal) ? Country.Undefined
                                    : (Country)(int)rdr["Country"];

从您的评论中,您似乎已将枚举的数值存储在varchar列中,将您的数字转换为字符串 如果你想将这个字符串转换回适当的枚举值,那么你应该使用Enum.TryParse,但转换回来并不像看起来那么简单。

因此,如果您仍想检查空值,那么:

int ordinal = rdr.GetOrdinal("Country");
// Check for null value....
if(rdr.IsDBNull(ordinal))
    inf.Country = Country.Undefined;
else
{
    // OK, not null, but what if it is "ABC"??
    if(!Enum.TryParse(rdr["Country"].ToString(), out inf.Country))
       inf.Country = Country.Undefined;

    // OK, but what if it is a number not defined in the coutry enum (IE "88")
    if(!Enum.IsDefined(typeof(Country), inf.Country))
       inf.Country = Country.Undefined;
}

如您所见,如果没有特定原因,我建议将枚举值存储为整数而不是字符串。这样可以在代码中以及将来对此变量进行更改时提供更大的灵活性。

答案 1 :(得分:0)

试试这个

 if (rdr["Country"]!=DBNull.Value)
 {
 inf.Country  =(Country)Enum.ToObject(typeof(Country) , rdr["Country"].ToString());
 }