7

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

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

我目前将枚举用于 NotificationMethod(无,电子邮件,Sms),
性别(男性,女性)OrderStatus(打开,关闭,InProgres,DeliveryInProgress PaymentService(现金,BankTransfer,Paypal,GoogleWallet)等值

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

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

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

而不是枚举值 Email 我想显示 E-Mail 并且我想要单词之间的空格。

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

我的 order 和 Preference db 表每个表我有大约 20 个这样的枚举。

对于我的情况,最好的做法是

  1. 仅使用具有枚举属性的 C# 枚举来显示值,如 FriendlyNames、Description、Tooltip。

  2. 只需使用数据库查找表。缺点是业务规则必须基于查找表中所选值的字符串值。要进入我的偏好或订单编辑屏幕,我必须分别读取数据库中的 20 个查找表才能呈现下拉控件。这使得编写代码和报告变得更加容易,但系统将承受重负载(系统有成千上万的用户)

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

你如何决定最好的设计决策或有更好的解决方案?

4

2 回答 2

6

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

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

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

这似乎相关:SQL Table and C# Enumeration

为了对此进行扩展,我们还使用反射来获取枚举的 DisplayValue 属性。但是,仅仅因为我们这样做并不能使其成为最佳实践。我们在客户端机器上运行,而不是在云中,因此反射不是一个大问题。我不知道当您从一台机器上为多个用户提供页面时,这种反映会有多大。也就是说,微软在使用 HTML Helpers 时充分利用了反射,反射可能比访问数据库快 20 次。但我离题了...

于 2013-09-20T00:54:51.733 回答
3

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

给定using resx = namespace.resxFile(我建议一个 .resx 文件专门用于保存枚举值的标题 - 即我会将其他 UI 资源放在另一个文件中)每个枚举值都存储为按约定命名的字符串[enumValue]Caption,您的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();

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

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

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

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

于 2013-09-20T01:32:20.367 回答