正確姿勢?EF Core 中這樣使用列舉類型?

正確姿勢?EF Core 中這樣使用列舉類型?

在EntityFramework Core中的實體是不直接支援列舉類型的操作,這讓我們在開發過程中帶來不少的麻煩

最後更新 2021/11/9 上午10:06
waitaction
預計閱讀 3 分鐘
分類
EF Core
標籤
.NET C# EF Core ORM .NET Core

在 EntityFramework Core 中的實體並不直接支援列舉類型的操作,這讓我們在開發過程中帶來不少麻煩,下面總結一下在 ef core 中使用列舉的方法。

例如下面的 MsgInfo 實體,對應著資料庫表 MsgInfo,其中欄位 SendState 發送狀態在業務邏輯上有 發送成功發送失敗 兩種列舉狀態。但 ef 把它生成為 int 類型,而不是列舉,當然也不能修改成列舉,這樣會導致 ef 寫入和讀取資料異常。

原來的實體

public partial class MsgInfo
{
    public string Id { get; set; }
    public string UserAddress { get; set; }
    public string Content { get; set; }
    public int SendState { get; set; }
}

這裡新增一個欄位 SendStateEnum 設定為列舉類型,並使用 [NotMapped] 為不映射到資料庫,為了防止輸出 HTTP 時被序列化,也可以添加 [Newtonsoft.Json.JsonIgnore] 標記

需添加 NuGet 套件 Newtonsoft.Json

修改完的實體程式碼如下

修改實體

public partial class MsgInfo
{
    public string Id { get; set; }
    public string UserAddress { get; set; }
    public string Content { get; set; }
    public int SendState { get; set; }

    [NotMapped]
    [Newtonsoft.Json.JsonIgnore]
    public SendStateEnum SendStateEnum
    {
        get
        {
            switch (SendState)
            {
                case (int)SendStateEnum.Fail:
                    return SendStateEnum.Fail;
                case (int)SendStateEnum.Success:
                    return SendStateEnum.Success;
                default:
                    return SendStateEnum.UnKnow;
            }
        }
        set
        {
            SendState = (int)value;
        }

    }
}
public enum SendStateEnum
{
    Success = 1,
    Fail = 2,
    UnKnow =3
}

添加了 SendStateEnum 欄位後,以後使用 ef core 操作或者讀取 SendStateEnum 代替了 SendState 欄位(註:站長實測與原文有出入,如下面的程式碼(原文程式碼)貌似應該使用 SendState 進行 EF Core 的操作,如有不同意見請留言指正。

using (var context = new FrameworkDbContext())
{
    var result = context.MsgInfo.Where(m => m.SendStateEnum == SendStateEnum.Success);
}

當然,為了防止原來的 SendState 欄位被使用,可以添加標記 [Obsolete] 提醒使用者該欄位 SendState 已過時。

修改後的最終實體程式碼如下

public partial class MsgInfo
{
    public string Id { get; set; }
    public string UserAddress { get; set; }
    public string Content { get; set; }

    [Obsolete]
    public int SendState { get; set; }

    [NotMapped]
    [Newtonsoft.Json.JsonIgnore]
    public SendStateEnum SendStateEnum
    {
        get
        {
            switch (SendState)
            {
                case (int)SendStateEnum.Fail:
                    return SendStateEnum.Fail;
                case (int)SendStateEnum.Success:
                    return SendStateEnum.Success;
                default:
                    return SendStateEnum.UnKnow;
            }
        }
        set
        {
            SendState = (int)value;
        }
    }
}
public enum SendStateEnum
{
    Success = 1,
    Fail = 2,
    UnKnow =3
}
繼續探索

延伸閱讀

更多文章