将entity framework中的字符串列映射到枚举
有没有办法将字符串列映射到实体模型中的枚举?
我在Hibernate中做过这个,但是无法在EMF中弄明白。
这很难看,但是为了将枚举映射到字符串,我发现了这样的东西:
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是它的字符串版本。
可能是一个更好的版本。
OrderStateIdentifier字段用于JSON序列化和数据库字段,而OrderState仅在代码中用于方便。
public string OrderStateIdentifier { get { return OrderState.ToString(); } set { OrderState = value.ToEnum(); } } [NotMapped] [JsonIgnore] public OrderState OrderState { get; set; } public static class EnumHelper { /// /// Converts string to enum value (opposite to Enum.ToString()). /// /// Type of the enum to convert the string into. /// string to convert to enum value. public static T ToEnum(this string s) where T: struct { T newValue; return Enum.TryParse(s, out newValue) ? newValue : default(T); } }
我认为还有另一个解决方案。
我们最近在项目中所做的是使用扩展方法。
我写了两个,一个用于Enum,一个用于实体,但这里是示例:
namespace Foo.Enums { [DataContract] public enum EAccountStatus { [DataMember] Online, [DataMember] Offline, [DataMember] Pending }
…枚举本身,现在包含静态类的扩展方法:
public static class AccountStatusExtensionMethods { /// /// Returns the Type as enumeration for the db entity /// /// Entity for which to check the type /// enum that represents the type 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!"); }
…实体类型的扩展方法,以及缩短输入的便捷方法:
/// /// Gets the String representation for this enums choosen /// /// Instance of the enum chosen /// Name of the chosen enum in String representation 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"; }
为了在数据库端添加validation,您可以添加一个检查约束来validation该列是否为期望值(您也可以在映射到枚举时执行此操作,但由于该属性只是一个字符串,这有助于确保您的消费者api正确设置值)。
ALTER TABLE [PocoEntity] ADD CONSTRAINT [CHK_PocoEntity_Status] CHECK ([Status] in ('ok', 'failed'));
它位于EF7的路线图上: https : //github.com/aspnet/EntityFramework/issues/242
你可能想投票支持它: http : //data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/2639292-simple-type-mapping-or-mapped-type-conversion-sup
我有同样的问题。 我想出了一个解决方案,但我并不完全满意。
我的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(value); } } [NotMapped] public Gender Gender { get; set; } }
这是从字符串中获取正确枚举的扩展方法。
public class EnumExtensions { public static T ParseEnum(string value) { return (T)Enum.Parse(typeof(T), value, true); } }
我写了一篇关于此的博客文章 – http://nodogmablog.bryanhogan.net/2014/11/saving-enums-as-strings-with-entity-framework/
如果要将枚举值映射到另一个对应字符串(例如缩写),可以使用以下方法:
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 DictValorTipoDado = new Dictionary() { { TipoDado.Texto, "T" }, { TipoDado.Numerico, "N" }, { TipoDado.Data, "D" } }; public enum TipoDado { Texto, Numero, Data } }