[英]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.