[英]Map string column in Entity Framework to Enum
有没有办法将字符串列映射到实体模型中的枚举?
我在Hibernate中做过这个,但无法在EMF中弄明白。
可能是一个更好的版本。
OrderStateIdentifier字段用于JSON序列化和数据库字段,而OrderState仅在代码中用于方便。
public string OrderStateIdentifier
{
get { return OrderState.ToString(); }
set { OrderState = value.ToEnum<OrderState>(); }
}
[NotMapped]
[JsonIgnore]
public OrderState OrderState { get; set; }
public static class EnumHelper
{
/// <summary>
/// Converts string to enum value (opposite to Enum.ToString()).
/// </summary>
/// <typeparam name="T">Type of the enum to convert the string into.</typeparam>
/// <param name="s">string to convert to enum value.</param>
public static T ToEnum<T>(this string s) where T: struct
{
T newValue;
return Enum.TryParse(s, out newValue) ? newValue : default(T);
}
}
它很难看,但是为了将枚举映射到字符串,我发现了这样的东西:
public virtual string StatusString
{
get { return Status.ToString(); }
set { OrderStatus newValue;
if (Enum.TryParse(value, out newValue))
{ Status = newValue; }
}
}
public virtual OrderStatus Status { get; set; }
OrderStatus是枚举器类型,Status是枚举器,StatusString是它的字符串版本。
我认为还有另一个解决方案。
我们最近在项目中所做的是使用扩展方法。
我写了两个,一个用于Enum,一个用于实体,但这里是示例:
namespace Foo.Enums
{
[DataContract]
public enum EAccountStatus
{
[DataMember]
Online,
[DataMember]
Offline,
[DataMember]
Pending
}
...枚举本身,现在包含静态类的扩展方法:
public static class AccountStatusExtensionMethods
{
/// <summary>
/// Returns the Type as enumeration for the db entity
/// </summary>
/// <param name="entity">Entity for which to check the type</param>
/// <returns>enum that represents the type</returns>
public static EAccountStatus GetAccountStatus(this Account entity)
{
if (entity.AccountStatus.Equals(EAccountStatus.Offline))
{
return EAccountStatus.Offline;
}
else if (entity.AccountStatus.Equals(EAccountStatus.Online))
{
return EAccountStatus.Online;
}
else if (entity.AccountStatus.Equals(EAccountStatus.Pending))
{
return EAccountStatus.Pending;
}
throw new System.Data.Entity.Validation.DbEntityValidationException(
"Unrecognized AccountStatus was set, this is FATAL!");
}
...实体类型的扩展方法,以及缩短输入的便捷方法:
/// <summary>
/// Gets the String representation for this enums choosen
/// </summary>
/// <param name="e">Instance of the enum chosen</param>
/// <returns>Name of the chosen enum in String representation</returns>
public static String GetName(this EAccountStatus e)
{
return Enum.GetName(typeof(EAccountStatus), e);
}
}
}
......最后用法:
// to set always the same, mappable strings:
db.AccountSet.Single(m => m.Id == 1).Status = EAccountStatus.Online.GetName();
// to get the enum from the actual Entity you see:
EAccountStatus actualStatus = db.AccountSet.Single(m => m.Id == 1).GetAccountStatus();
现在,你只需要“使用Foo.Enums;” 你可以在实体和枚举上调用方法。 更好的是,在您的实体的某种包装中,您还可以在不同类型之间进行无缝编组,这些类型代表大项目中的相同事物。
唯一值得注意的是,在将Linq表达式传递给Linq之前,有时必须执行扩展方法。 这里的问题是Linq无法在自己的上下文中执行扩展方法...
也许只是一种替代方案,但我们已经这样做了,因为它为您提供了如何为实体获取内容的极大灵活性。 您可以轻松编写扩展程序以在ShoppingCart中接收帐户实际产品...
问候,Kjellski
另一种方法是使用带有字符串const字段而不是枚举的静态类。
例如:
public class PocoEntity
{
public string Status { get; set; }
}
public static class PocoEntityStatus
{
public const string Ok = "ok";
public const string Failed = "failed";
}
为了在数据库端添加验证,您可以添加一个检查约束来验证该列是否为预期值(您也可以在映射到枚举时执行此操作,但由于该属性只是一个字符串,这有助于确保您的消费者api正确设置值)。
ALTER TABLE [PocoEntity]
ADD CONSTRAINT [CHK_PocoEntity_Status]
CHECK ([Status] in ('ok', 'failed'));
你可以这样做:
将类中的Enum属性装饰为文本列
[Column(TypeName = "nvarchar(50)")]
public FileTypes FileType { get; set; }
要么
在DatabaseContext
类中,重写OnModelCreating
并添加:
modelBuilder
.Entity<File>()
.Property(e => e.FileType)
.HasConversion(new EnumToStringConverter<FileTypes>());
如果要将枚举值映射到另一个对应字符串(例如缩写),可以使用以下方法:
public class MinhaClasse
{
public string CodTipoCampo { get; set; }
[NotMapped]
public TipoDado TipoCampo
{
get => DictValorTipoDado.SingleOrDefault(e => e.Value == CodTipoCampo).Key;
set => CodTipoCampo = DictValorTipoDado[value];
}
private Dictionary<TipoDado, string> DictValorTipoDado = new Dictionary<TipoDado, string>()
{
{ TipoDado.Texto, "T" },
{ TipoDado.Numerico, "N" },
{ TipoDado.Data, "D" }
};
public enum TipoDado { Texto, Numero, Data }
}
我有同样的问题。 我想出了一个解决方案,但我并不完全满意。
我的Person
类有一个Gender
枚举,我使用数据注释将字符串映射到数据库并忽略枚举。
public class Person
{
public int PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Column("Gender")]
public string GenderString
{
get { return Gender.ToString(); }
private set { Gender = EnumExtensions.ParseEnum<Gender>(value); }
}
[NotMapped]
public Gender Gender { get; set; }
}
这是从字符串中获取正确枚举的扩展方法。
public class EnumExtensions
{
public static T ParseEnum<T>(string value)
{
return (T)Enum.Parse(typeof(T), value, true);
}
}
我写了一篇关于此的博客文章 - http://nodogmablog.bryanhogan.net/2014/11/saving-enums-as-strings-with-entity-framework/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.