简体   繁体   English

我如何在数据库中存储枚举

[英]How I store Enumerations in the Database

One of the things I come across in databases now and then is a collection of single tables with a name like "MessageType". 我时不时要在数据库中遇到的一件事是名称如“ MessageType”的单个表的集合。 You have a look in them and it turns out to have 6 or so rows with no foreign key relationships. 您看一下它们,结果发现有6行左右没有外键关系。 Every single time it turns out to be someone had the idea to store an Enumeration (Enum) type in the database. 事实证明,每一次有人都会想到将Enumeration(Enum)类型存储在数据库中。 Not a bad idea as it turns out since you can add sort options, soft deletes and the like, but the implementation of a single table for each one is flawed. 事实证明这不是一个坏主意,因为您可以添加排序选项,软删除等,但是为每个表实现单个表是有缺陷的。

"Domain" (or "type") is a fundamental part of relational theory. “域”(或“类型”)是关系理论的基本组成部分。 By definition, it's a set of all possible values of the type in question. 根据定义,它是所讨论类型的所有可能值的集合。 (Among other things.) (除其他事项外。)

In some cases, it's impractical or unnecessary to store the set of such values in a table. 在某些情况下,将此类值的集合存储在表中是不切实际或不必要的。

  • It's not practical to store the set of personal names. 存储一组个人名称是不切实际的。
  • It's not necessary to store the set of integers. 不必存储整数集。

But in other cases, it makes sense to store the set of all possible values. 但是在其他情况下,存储所有可能值的集合是有意义的。 In a SQL database, you can store that set as part of a CHECK constraint. 在SQL数据库中,您可以将该设置存储为CHECK约束的一部分。 You can also store that set in a table. 您也可以将该集合存储在表中。 The biggest advantage of storing that set in a table is that no code has to be changed when you're surprised to discover a value that you didn't initially know was a member of that set. 将集合存储在表中的最大好处是,当您惊讶地发现最初不知道是该集合成员的值时,无需更改任何代码。

So, at a certain theoretical level, you could say that every column in a relational database maps to a foreign key reference to a table containing the set of all possible values. 因此,在一定的理论水平上,您可以说关系数据库中的每一列都映射到一个外键引用,该引用指向包含所有可能值集合的表。 But when it's time to build a database, a lot of those tables might be eliminated as either impractical or unnecessary. 但是,当需要构建数据库时,由于不切实际或不必要,这些表中的许多表可能会被淘汰。

And others might not. 其他人可能不会。

I'm not sure whether this is what you meant, but if you look at this kind of table you won't see any foreign key references. 我不确定这是否意味着您的意思,但是如果您查看这种表,将不会看到任何外键引用。 Relevant foreign key references will always be in other tables, referencing this set of all possible values. 相关外键引用将始终在其他表中,并引用所有可能值的集合。

An enumeration is effective a set of lookup values though, each with a name and an explicit value - so you could argue that each one does map well to a reference table. 枚举实际上是一组查找值的有效值,每个查找值都有一个名称和一个显式值-因此您可能会争辩说每个查找值确实可以很好地映射到引用表。 If you enforce a foreign key constraint anywhere where these enumerated values are stored, then you also ensure that the data is always within range. 如果在存储这些枚举值的任何地方强制执行外键约束,则还应确保数据始终在范围内。

It depends what your scenario is. 这取决于您的情况。 I've done applications before where I've used "Enum" tables - but more commonly I simply have strongly typed enumerations in my code that then translate into literal strings when they get committed to the database. 我已经在使用“ Enum”表之前完成了应用程序-但是更常见的是,我只是在代码中强类型化了枚举,然后在将它们提交到数据库时将其转换为文字字符串。

eg 例如

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

I don't think there is a right or wrong way. 我认为没有正确或错误的方法。

Storing each enum type in a column of its own is good design. 将每个枚举类型存储在其自己的列中是很好的设计。 Storing enum values from different types in the same column is bad design, even if you use a second column to disambiguate. 即使使用第二列来消除歧义,将来自不同类型的枚举值存储在同一列中也是不好的设计。 Once you've decided to use a separate column for each type, the additional cost of storing that column in a table of its own is minimal. 一旦决定为每种类型使用单独的列,将该列存储在其自己的表中的额外成本将降至最低。

I would generally have an Id field in that table, and would use that Id field as the target for any needed foreign key references to the enum instance. 我通常在该表中有一个Id字段,并将该Id字段用作对枚举实例的任何需要的外键引用的目标。 Such a table can be used for validation and lookup. 这样的表可以用于验证和查找。

For a large and complex database, one with about 500 tables in it, it wouldn't be uncommon for about 150 of those tables to be lookup tables. 对于一个大型且复杂的数据库(其中包含约500个表),将其中约150个表作为查找表并不少见。

Personally I think it is a good idea to store enumerations in database if enum values are used in other types of entities. 我个人认为,如果在其他类型的实体中使用枚举值,则将枚举存储在数据库中是个好主意。 Furthermore, it is very common to store each enum in different table, otherwise foreign key relationships will not be correct. 此外,将每个枚举存储在不同的表中非常常见,否则外键关系将不正确。

For example, if MessageType enum has values: 例如,如果MessageType枚举具有值:

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

Then, corresponding table will have the following structure: 然后,对应的表将具有以下结构:

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

Here, ID holds the integer values from our MessageType enum (1 => "Alert", 2 => "Error", 3 => "Log"), and is used as a foreign key where needed. 在这里, ID保存我们MessageType枚举的整数值(1 =>“ Alert”,2 =>“ Error”,3 =>“ Log”),并在需要时用作外键。

In addition, in code there remains no big need to manipulate the data from MessageTypes table, thus minimizing the data transfer sizes from/to database. 此外,在代码中,无需MessageTypes地操作MessageTypes表中的数据,从而最大程度地减少了数据库之间的数据传输大小。

For example, consider this database table: 例如,考虑以下数据库表:

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

In code we probably will have the corresponding entity class like this: 在代码中,我们可能会有对应的实体类,如下所示:

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

So, when we retrieve the Message entity, we don't need to retrieve the corresponding row from MessageTypes table, neither we need to have a separate entity like MessageType. 因此,当我们检索Message实体时,我们不需要从MessageTypes表中检索相应的行,也不需要像MessageType这样的单独实体。 Instead, we can directly use already known enum values for checking the message type: 相反,我们可以直接使用已知的枚举值检查消息类型:

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

I hope this makes sense. 我希望这是有道理的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM