对云中的asp.net MVC应用程序使用枚举或数据库查找表或两者的最佳实践/设计决策是什么?

时间:2021-06-04 20:07:23

I am writing an Asp.net MVC app but I am not sure of a design decision. I am unsure if the best design would be to use enum values or store these values as lookup tables in the database. I can imagine lookup tables is fine for a windows app where all these queries are not a problem but for a high traffic web application running in the cloud that uses a relational database I am not so sure.

我正在编写一个Asp.net MVC应用程序,但我不确定是否有设计决定。我不确定最好的设计是使用枚举值还是将这些值存储为数据库中的查找表。我可以想象查找表适用于Windows应用程序,其中所有这些查询都不是问题,但对于在云中运行的高流量Web应用程序,使用关系数据库我不太确定。

The application needs to be maintainable and will need to support multi language in future. Other developers are going to have to work on the system so I need the design correct and easily maintainable.

应用程序需要可维护,并且将来需要支持多语言。其他开发人员将不得不在系统上工作,因此我需要设计正确且易于维护。

I currently use enums for values like NotificationMethod (None, Email,Sms),
Gender (Male, Female) OrderStatus (Open,Closed,InProgres, DeliveryInProgress PaymentService (Cash, BankTransfer,Paypal, GoogleWallet)

我目前使用枚举值来表示NotificationMethod(无,电子邮件,短信),性别(男性,女性)OrderStatus(Open,Closed,InProgres,DeliveryInProgress PaymentService(Cash,BankTransfer,Paypal,GoogleWallet))

enums suit me as there are business rules in the code linked to the enum and having business rules with enums values instead of strings make the application more readable and less prone to mistakes.

枚举适合我,因为链接到枚举的代码中有业务规则,并且具有枚举值而不是字符串的业务规则使应用程序更具可读性并且更不容易出错。

However the above is not suitable for the following scenario. My web frontend has a select/dropdown controls. To populate the dropdowns I have the following code

但是,上述情况不适合以下情况。我的网络前端有一个选择/下拉控件。要填充下拉列表,我有以下代码

  var paymentServices=
          Enum.GetValues(typeof(PaymentService))
          .Cast<PaymentService >()
          .Select(d => new SelectListItem()
          {
              Text = d.ToString(),
              Value = ((int)d).ToString()
          }).ToList();

instead of the enum value Email I want to display E-Mail and I would want spaces between words.

而不是枚举值电子邮件我想显示电子邮件,我想要在单词之间的空格。

So I end up using attributes and the use a static method in an EnumHelper Class to read the attributes as described here

所以我最终使用属性并在EnumHelper类中使用静态方法来读取这里描述的属性

My order and Preference db tables I have about 20 of these enums each per table.

我的订单和首选项数据库表我每个表中有大约20个这些枚举。

For my scenario is it best practice to

对于我的场景是最好的做法

  1. Use only C# enums with enum attributes for display values like FriendlyNames, Description, Tooltip.

    仅使用带有枚举属性的C#枚举来显示诸如FriendlyNames,Description,Tooltip等显示值。

  2. Just use database lookup tables. Disadvantage is business rules will have to be based on String values of the selected value that is in the lookup table. To go to my preference or order edit screens I would have to read 20 lookup tables separately in the database in order to render the dropdown controls. This makes writing code and reporting much easier but the system will be under heavy load (the system has thousands of users)

    只需使用数据库查找表。缺点是业务规则必须基于查找表中所选值的String值。要转到我的首选项或订购编辑屏幕,我必须在数据库中单独读取20个查找表,以便呈现下拉控件。这使得编写代码和报告变得更加容易,但系统将负载很重(系统有数千个用户)

  3. Have simple enums values for business rules and use matching lookup database tables and store in those tables the additional display columns to show on the frontend UI. The disadvantage is I have to keep the basic enum numbering in sync with the database lookup tables.

    为业务规则提供简单的枚举值,并使用匹配的查找数据库表,并在这些表中存储要在前端UI上显示的其他显示列。缺点是我必须使基本枚举编号与数据库查找表保持同步。

How do you I decide the best design decision or is there a better solution?

您如何决定最佳设计决策还是有更好的解决方案?

2 个解决方案

#1


3  

If your enum values are going to need to be localized, why not be proactive about it and use a .resx file right away for English captions? Using attributes means you're statically declaring what the description should be for each enum value, and that's essentially the opposite of being localizable.

如果您的枚举值需要进行本地化,为什么不主动使用它并立即使用.resx文件获取英文字幕?使用属性意味着您静态地声明每个枚举值的描述​​应该是什么,这基本上与可本地化相反。

Given using resx = namespace.resxFile (I'd suggest a .resx file dedicated to hold captions for enum values - i.e. I'd put the other UI resources in another file) with each enum value being stored as a string named by convention [enumValue]Caption, your paymentServices list could look like this:

给定使用resx = namespace.resxFile(我建议使用.resx文件专用于保存枚举值的标题 - 即我将其他UI资源放在另一个文件中),每个枚举值存储为由约定命名的字符串[ enumValue]标题,您的paymentServices列表可能如下所示:

var paymentServices =
    Enum.GetValues(typeof(PaymentService))
        .Cast<PaymentService>()
        .Select(d => new SelectListItem()
        {
            Text = resx.ResourceManager
                       .GetString(string.Format("{0}Caption", d.ToString())),
            Value = ((int)d).ToString()
        }).ToList();

When comes the time to localize, all you'll need to do is translate your .resx file and set the resource's culture to the desired one.

到了本地化的时候,您需要做的就是翻译您的.resx文件并将资源的文化设置为所需的文化。

The downside is obviously you can't have a feature that, for example, would let users edit the translations and add new supported languages, since the .resx file is built into your app; this also means code needs to change whenever a new enum value is needed.

缺点显然是你不能拥有一个功能,例如,让用户编辑翻译并添加新支持的语言,因为.resx文件内置在你的应用程序中;这也意味着只要需要新的枚举值,代码就需要改变。

The upside is that you're not hitting the database, and your code is self-contained, meaning future devs don't need to lookup anything anywhere else than in the code base.

好处是您没有访问数据库,并且您的代码是自包含的,这意味着未来的开发人员不需要在代码库之外的任何地方查找任何内容。

Which is best really boils down to what your needs and requirements are.

哪个最好的归结为您的需求和要求。

#2


6  

Have simple enums values for business rules and use matching lookup database tables and store in those tables the additional display columns to show on the frontend UI. The disadvantage is I have to keep the basic enum numbering in sync with the database lookup tables.

为业务规则提供简单的枚举值,并使用匹配的查找数据库表,并在这些表中存储要在前端UI上显示的其他显示列。缺点是我必须使基本枚举编号与数据库查找表保持同步。

You could investigate T4 templates, which would mean the enumerations in your application are built from the lookup tables in your database semi-automatically. (You choose an option from the build menu to recreate all of them.) We currently do this on a large project at work and it works well.

您可以调查T4模板,这意味着应用程序中的枚举是半自动地从数据库中的查找表构建的。 (您可以从构建菜单中选择一个选项来重新创建所有选项。)我们目前在一个大型项目中执行此操作并且运行良好。

The benefit is, of course, you don't have to have magic numbers in your application or keep things in sync manually. Foreign keys and strongly-typed code, a win-win.

当然,好处是您不必在应用程序中使用幻数或手动保持同步。外键和强类型代码,双赢。

This seems related: SQL Table and C# Enumeration

这看起来很相关:SQL Table和C#Enumeration

To expand upon this, we also use reflection to get the DisplayValue attributes for enums. However, just because we do it doesn't make it best practice. We run on client machines, not in the cloud, so therefore reflection isn't as big of an issue. I don't know how substantial that reflection would be when you have multiple users being served up pages from one machine. That said, Microsoft makes ample use of reflection when using HTML Helpers, and reflection could be faster than hitting the database 20 times. But I digress...

为了扩展这一点,我们还使用反射来获取枚举的DisplayValue属性。但是,仅仅因为我们这样做并不是最佳实践。我们在客户端计算机上运行,​​而不是在云中运行,因此反射不是一个大问题。我不知道当你有多个用户从一台机器上提供服务时,反射会有多大。也就是说,Microsoft在使用HTML Helpers时充分利用了反射,并且反射速度可能比使用数据库20次更快。但我离题了......

#1


3  

If your enum values are going to need to be localized, why not be proactive about it and use a .resx file right away for English captions? Using attributes means you're statically declaring what the description should be for each enum value, and that's essentially the opposite of being localizable.

如果您的枚举值需要进行本地化,为什么不主动使用它并立即使用.resx文件获取英文字幕?使用属性意味着您静态地声明每个枚举值的描述​​应该是什么,这基本上与可本地化相反。

Given using resx = namespace.resxFile (I'd suggest a .resx file dedicated to hold captions for enum values - i.e. I'd put the other UI resources in another file) with each enum value being stored as a string named by convention [enumValue]Caption, your paymentServices list could look like this:

给定使用resx = namespace.resxFile(我建议使用.resx文件专用于保存枚举值的标题 - 即我将其他UI资源放在另一个文件中),每个枚举值存储为由约定命名的字符串[ enumValue]标题,您的paymentServices列表可能如下所示:

var paymentServices =
    Enum.GetValues(typeof(PaymentService))
        .Cast<PaymentService>()
        .Select(d => new SelectListItem()
        {
            Text = resx.ResourceManager
                       .GetString(string.Format("{0}Caption", d.ToString())),
            Value = ((int)d).ToString()
        }).ToList();

When comes the time to localize, all you'll need to do is translate your .resx file and set the resource's culture to the desired one.

到了本地化的时候,您需要做的就是翻译您的.resx文件并将资源的文化设置为所需的文化。

The downside is obviously you can't have a feature that, for example, would let users edit the translations and add new supported languages, since the .resx file is built into your app; this also means code needs to change whenever a new enum value is needed.

缺点显然是你不能拥有一个功能,例如,让用户编辑翻译并添加新支持的语言,因为.resx文件内置在你的应用程序中;这也意味着只要需要新的枚举值,代码就需要改变。

The upside is that you're not hitting the database, and your code is self-contained, meaning future devs don't need to lookup anything anywhere else than in the code base.

好处是您没有访问数据库,并且您的代码是自包含的,这意味着未来的开发人员不需要在代码库之外的任何地方查找任何内容。

Which is best really boils down to what your needs and requirements are.

哪个最好的归结为您的需求和要求。

#2


6  

Have simple enums values for business rules and use matching lookup database tables and store in those tables the additional display columns to show on the frontend UI. The disadvantage is I have to keep the basic enum numbering in sync with the database lookup tables.

为业务规则提供简单的枚举值,并使用匹配的查找数据库表,并在这些表中存储要在前端UI上显示的其他显示列。缺点是我必须使基本枚举编号与数据库查找表保持同步。

You could investigate T4 templates, which would mean the enumerations in your application are built from the lookup tables in your database semi-automatically. (You choose an option from the build menu to recreate all of them.) We currently do this on a large project at work and it works well.

您可以调查T4模板,这意味着应用程序中的枚举是半自动地从数据库中的查找表构建的。 (您可以从构建菜单中选择一个选项来重新创建所有选项。)我们目前在一个大型项目中执行此操作并且运行良好。

The benefit is, of course, you don't have to have magic numbers in your application or keep things in sync manually. Foreign keys and strongly-typed code, a win-win.

当然,好处是您不必在应用程序中使用幻数或手动保持同步。外键和强类型代码,双赢。

This seems related: SQL Table and C# Enumeration

这看起来很相关:SQL Table和C#Enumeration

To expand upon this, we also use reflection to get the DisplayValue attributes for enums. However, just because we do it doesn't make it best practice. We run on client machines, not in the cloud, so therefore reflection isn't as big of an issue. I don't know how substantial that reflection would be when you have multiple users being served up pages from one machine. That said, Microsoft makes ample use of reflection when using HTML Helpers, and reflection could be faster than hitting the database 20 times. But I digress...

为了扩展这一点,我们还使用反射来获取枚举的DisplayValue属性。但是,仅仅因为我们这样做并不是最佳实践。我们在客户端计算机上运行,​​而不是在云中运行,因此反射不是一个大问题。我不知道当你有多个用户从一台机器上提供服务时,反射会有多大。也就是说,Microsoft在使用HTML Helpers时充分利用了反射,并且反射速度可能比使用数据库20次更快。但我离题了......