簡體   English   中英

將實體框架中的字符串列映射到枚舉

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM