Entity framework 在linq查询MVC 2.0中将字符串解析为poco类枚举
我有以下enum和POCO类Entity framework 在linq查询MVC 2.0中将字符串解析为poco类枚举,entity-framework,asp.net-mvc-2,enums,asp.net-4.0,Entity Framework,Asp.net Mvc 2,Enums,Asp.net 4.0,我有以下enum和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; s
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,
};
不幸的是,我遇到一个错误,无法将类型“string”隐式转换为“Model.Gender”
我想将正在从实体框架查询的字符串转换为我的性别枚举,并将其分配给我的POCO类。
试一试
将字符串作为枚举之一进行分析
这里有一个解决办法,但它意味着改变你漂亮干净的POCO
实体框架中不支持枚举。亚历克斯·詹姆斯(Alex James)提出了一个变通方案,但涉及面很广 相反,我更喜欢这样做:
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,它映射到概念侧的字节
然后,可以使用字节枚举映射到模型属性和从模型属性映射:
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,因为您为性别设置了字节字段,那么您还可以访问枚举属性GenderType
这解决了您的问题吗?我熟悉的实体框架不支持枚举。EF使用您的查询表达式创建一条SQL语句,然后将其发送到服务器,如果它无法创建某个操作的SQL等价物,它将为该操作抛出NotSupportedException。如果希望返回一小部分数据,可以使用ToArray方法在内存中创建一个对象,从而与实体框架分离 这将在内存中创建一系列实体。然后,任何进一步的查询语句都将位于LINQ to对象领域,该领域允许将字符串解析为枚举:
return from myEntity in myEntities
select new MyDataContract
{
ID = myEntity.ID,
Gender g = (Gender)Enum.Parse(typeof(Gender), myEntity.Gender, true)
};
或者您甚至可以将其分解为foreach循环:
我刚刚尝试了这个,但是它实际上在LINQ查询中不起作用。使用Enum.Parse方法是产生问题的原因。出现NotSupportedException,异常消息为LINQ to Entities无法识别“System.Object ParseSystem.Type,System.String”方法,并且无法将此方法转换为存储表达式。没错,我使用另一种可能的解决方案/解决方法编辑了答案。我正在尝试使用此伪造枚举的方法。您可以帮助完成一个部分。我不知道在哪里创建这个复杂的类型,它看起来应该放在web.config中,但我不确定。您使用的是什么版本的EF?您是如何进行POCO ie的。您使用数据库表创建了一个EDMX,然后在查询过程中转换为POCO?还是像中一样先编写POCOs?这也给了我一个NotSupportedException类型的异常,错误消息是LINQ to Entities无法识别“System.Object ParseSystem.type,System.String”方法,并且该方法无法转换为存储表达式。嘿,这帮了大忙。这太糟糕了,它污染了POCO,但现在只能这样了。由于我使用的依赖项反转模式,我在使用伪枚举解决方案时运气不太好。很抱歉,我不能投票支持你的答案,因为我没有足够的代表。非常感谢。没有问题,请在答案中选择一个正确答案,无论哪个答案解决了你的问题。此外,如果您不想污染POCO,可以将其放在分部类中,或者创建一个扩展方法。不过,在那里拥有房产并没有什么错,我是这样做的。不要让你的领域模型变得贫乏。
return from p in _db.People
select new Model.Person
{
PersonId = p.PersonId,
LastName = p.LastName,
FirstName = p.FirstName,
Gender = p.Gender, // sets byte
};
var myEntities = (from entity in _db.Entities
where /* condition */
select entity)
.ToArray();
return from myEntity in myEntities
select new MyDataContract
{
ID = myEntity.ID,
Gender g = (Gender)Enum.Parse(typeof(Gender), myEntity.Gender, true)
};
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();