簡體   English   中英

我如何在數據庫中存儲枚舉

[英]How I store Enumerations in the Database

我時不時要在數據庫中遇到的一件事是名稱如“ MessageType”的單個表的集合。 您看一下它們,結果發現有6行左右沒有外鍵關系。 事實證明,每一次有人都會想到將Enumeration(Enum)類型存儲在數據庫中。 事實證明這不是一個壞主意,因為您可以添加排序選項,軟刪除等,但是為每個表實現單個表是有缺陷的。

“域”(或“類型”)是關系理論的基本組成部分。 根據定義,它是所討論類型的所有可能值的集合。 (除其他事項外。)

在某些情況下,將此類值的集合存儲在表中是不切實際或不必要的。

  • 存儲一組個人名稱是不切實際的。
  • 不必存儲整數集。

但是在其他情況下,存儲所有可能值的集合是有意義的。 在SQL數據庫中,您可以將該設置存儲為CHECK約束的一部分。 您也可以將該集合存儲在表中。 將集合存儲在表中的最大好處是,當您驚訝地發現最初不知道是該集合成員的值時,無需更改任何代碼。

因此,在一定的理論水平上,您可以說關系數據庫中的每一列都映射到一個外鍵引用,該引用指向包含所有可能值集合的表。 但是,當需要構建數據庫時,由於不切實際或不必要,這些表中的許多表可能會被淘汰。

其他人可能不會。

我不確定這是否意味着您的意思,但是如果您查看這種表,將不會看到任何外鍵引用。 相關外鍵引用將始終在其他表中,並引用所有可能值的集合。

枚舉實際上是一組查找值的有效值,每個查找值都有一個名稱和一個顯式值-因此您可能會爭辯說每個查找值確實可以很好地映射到引用表。 如果在存儲這些枚舉值的任何地方強制執行外鍵約束,則還應確保數據始終在范圍內。

這取決於您的情況。 我已經在使用“ Enum”表之前完成了應用程序-但是更常見的是,我只是在代碼中強類型化了枚舉,然后在將它們提交到數據庫時將其轉換為文字字符串。

例如

public enum MessageType
{
    General,
    Comment,
    Feedback,
    Suggestions
}

我認為沒有正確或錯誤的方法。

將每個枚舉類型存儲在其自己的列中是很好的設計。 即使使用第二列來消除歧義,將來自不同類型的枚舉值存儲在同一列中也是不好的設計。 一旦決定為每種類型使用單獨的列,將該列存儲在其自己的表中的額外成本將降至最低。

我通常在該表中有一個Id字段,並將該Id字段用作對枚舉實例的任何需要的外鍵引用的目標。 這樣的表可以用於驗證和查找。

對於一個大型且復雜的數據庫(其中包含約500個表),將其中約150個表作為查找表並不少見。

我個人認為,如果在其他類型的實體中使用枚舉值,則將枚舉存儲在數據庫中是個好主意。 此外,將每個枚舉存儲在不同的表中非常常見,否則外鍵關系將不正確。

例如,如果MessageType枚舉具有值:

enum MessageType
{
    Alert = 1, /*each next will be incremented by 1*/
    Error,
    Log
}

然后,對應的表將具有以下結構:

table MessageTypes
{
    ID int,
    Name varchar(50)
}

在這里, ID保存我們MessageType枚舉的整數值(1 =>“ Alert”,2 =>“ Error”,3 =>“ Log”),並在需要時用作外鍵。

此外,在代碼中,無需MessageTypes地操作MessageTypes表中的數據,從而最大程度地減少了數據庫之間的數據傳輸大小。

例如,考慮以下數據庫表:

table Messages
{
    ID int,
    MessageTypeID int /*this is foreign key referring to Messages.ID*/,
    Text varchar(100)
}

在代碼中,我們可能會有對應的實體類,如下所示:

class Message
{
    int ID { get; set; }
    int MessageTypeID { get; set; }
    string Text { get; set; }
}

因此,當我們檢索Message實體時,我們不需要從MessageTypes表中檢索相應的行,也不需要像MessageType這樣的單獨實體。 相反,我們可以直接使用已知的枚舉值檢查消息類型:

var msg = LoadMessage(id: 101);
if (msg.MessageTypeID == (int)MessageType.Alert)
{
    Console.WriteLine("Alert: {0}", msg.Text);
}

我希望這是有道理的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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