在linq查询MVC 2.0中将字符串解析为poco类枚举

时间:2010-11-25 21:16:14

标签: entity-framework asp.net-mvc-2 enums asp.net-4.0

我有以下枚举和POCO类

public enum Gender
{
    Male,
    Female,
    Unknown
}

public class Person
{
    public int PersonId { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public Gender? Gender { get; set; }
}

我想在我的存储库中执行“获取所有人”查询,使其看起来像这样:

return from p in _db.People
       select new Model.Person
       {
          PersonId = p.PersonId,
          LastName = p.LastName,
          FirstName = p.FirstName,
          Gender = p.Gender,
       };

不幸的是我收到错误“无法将类型'字符串'隐式转换为'Model.Gender'”

我想将查询的字符串从实体框架转换为我的Gender枚举,并将其分配给我的POCO类。

4 个答案:

答案 0 :(得分:4)

实体框架不支持枚举。亚历克斯·詹姆斯有一种解决方法,但它非常复杂。

相反,我更喜欢这样做:

public enum Gender : byte
{
    Male = 1,
    Female,
    Unknown
}

public class Person
{
    public int PersonId { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public byte Gender { get; set; } // this is the EF model property
    public Gender GenderType // this is an additional custom property
    { 
        get { return (Gender) Gender; }
        set { Gender = (byte)value; }
    }
}

它基本上是实际值的钩子/包装器。在您的数据库中,将性别存储为tinyint(在概念方面映射到byte)。

然后,您可以使用字节枚举来映射模型属性:

return from p in _db.People
       select new Model.Person
       {
          PersonId = p.PersonId,
          LastName = p.LastName,
          FirstName = p.FirstName,
          Gender = p.Gender, // sets byte
       };

但是如果您访问该ViewModel,因为您设置了Gender的字节字段,您还可以访问枚举属性GenderType

这能解决您的问题吗?

答案 1 :(得分:1)

我熟悉的实体框架不支持枚举。 EF使用您的查询表达式创建一个SQL语句,然后将其发送到服务器,如果它无法创建某个操作的SQL等效项,则会为该操作抛出NotSupportedException。如果您希望返回一小组数据,可以使用ToArray方法在内存中创建对象,从而与实体框架分离。

var myEntities = (from entity in _db.Entities
                  where /* condition */
                  select entity)
                        .ToArray();

这将在内存中创建一系列实体。任何进一步的查询语句将在LINQ to Objects的领域中,它允许将字符串解析为枚举:

return from myEntity in myEntities
       select new MyDataContract
       {
            ID = myEntity.ID,
            Gender g = (Gender)Enum.Parse(typeof(Gender), myEntity.Gender, true)
       };

或者您甚至可以将其分解为foreach循环:

List<MyDataContract> myDataContracts = new List<MyDataContract>();
foreach (var myEntity in myEntities)
{
    var dataContract = new MyDataContract { ID = myEntity.ID };

    if (Enum.IsDefined(typeof(Gender), myEntity.Gender))
        dataContract.Gender = (Gender)Enum.Parse(typeof(Gender), myEntity.Gender, true);

        myDataContracts.Add(dataContract);
}

return myDataContracts.AsEnumerable();

答案 2 :(得分:0)

<击> 尝试

<击>
Gender = p.Gender != null ? (Gender)Enum.Parse(typeof(Gender), p.Gender) : (Gender?)null;

将字符串解析为其中一个枚举

这是一种解决方法,但这意味着要改变你漂亮干净的POCO

http://blogs.msdn.com/b/alexj/archive/2009/06/05/tip-23-how-to-fake-enums-in-ef-4.aspx

答案 3 :(得分:0)

   if (Enum.IsDefined(typeof(Gender), genderstring))
      Gender g = (Gender) Enum.Parse(typeof(Gender), genderstring, true);
   else
      //Deal with invalid string.