从关系数据库中检索“硬”值的最佳实践

时间:2012-09-17 18:45:10

标签: .net database

我想知道人们如何处理以下情况(假设这个想法可以解决)......

  • TABLE A (Orders): OrderId, StatusId等(状态表上的外键)
  • TABLE B (Statuses): StatusId, Name,

表B需要存在(IOW,我不能仅仅创建一个状态枚举),因为订单状态列表需要是动态的,因为业务需求和实践会发生变化,并且您的程序中有方法,如{{ 1}},GetAllOrders()GetAllStatuses()等等。但是,您似乎不断需要访问“硬编码”状态。例如,首次创建订单时,其状态为“新建”,您需要将其设置为该状态,而无需任何用户干预。也许你有一个GetUnfilledOrders报告,它返回所有“处理”的订单,同样没有用户选择他们正在寻找的状态,因为报告的名称暗示了他们想要的东西。我希望你明白这一点。

我在这些情况下一直在做的是创建一个设置,例如GetOrderByStatus(int statusId)并将其设置为我要用于新订单的状态的ID,或DefaultNewOrderStatus (int)再次设置设置要使用的状态列表。我的想法是,如果我们的状态“架构”发生变化,我可以动态更改这些设置。问题是需要使用的“硬编码”值的数量似乎在增长(可能现在我需要一个默认状态来设置已完成的订单,或者用于显示“打开”订单UI视图的状态列表,等等,以及处理它们的设置数量。

我非常有兴趣知道其他人如何处理这些情况?

4 个答案:

答案 0 :(得分:1)

我不确定我是否注意到了您的问题,但看起来您正试图以“硬编码”方式实施Business Process Manager。您实际需要的不是动态状态列表,而是动态的进程列表,实际上是如何使用状态的场景。此外,您需要采取措施,这将触发状态更改。所以,举个例子,你有一个状态列表:

  1. NEW
  2. 加工
  3. DELIVERY
  4. FINISHED
  5. 接下来是一系列行动:

    1. 创建新
    2. 开始处理
    3. 进入交付
    4. 完成交付
    5. RETURNED
    6. 现在,您可以设计一个流程:

      • [START] - > (创建新) - > NEW
      • 新 - > (开始处理) - >处理
      • 处理 - > (进入交付) - > DELIVERY
      • 交付 - > (已返回) - >加工
      • 交付 - > (完成交付) - > FINISHED

      您的应用程序需要有一组可以对上述操作的方法(通常是表单,一些向导等)。当某些内容发生变化时,您可以添加新状态,复制和修改该过程,并且您的应用程序已经知道如何处理它,例如您需要处理取消订单的问题。您可以将CANCEL添加到您的操作中,取消订单并创建新流程(或修改旧流程),添加:

      • 处理 - > (取消) - >取消

      因此,总而言之,您的问题不仅仅是状态更改,而是业务流程的变化。在这种情况下,您需要拥有动态流程,而不仅仅是状态。然而,问题消失了 - 但你需要重建你的应用程序 - 或者建立一个新的应用程序。

      修改

      关于报告,这是一个相当不同的情况。如果您找到了一种方法来准备能够生成任何报告的通用架构,那么您将会挑战商业智能,数据仓库概念等的实际形式: - )

答案 1 :(得分:0)

制作枚举。这个枚举是为了您的业务逻辑。您仍然可以从数据库查询中显示可用状态列表。

将StatusId转换为StatusEnum值时,您需要在数据库中包含新值。但是,你的所有逻辑都应该没问题,因为New仍然是New。如果需要编写使用新创建状态的逻辑,请更新枚举。

对于状态之类的东西,StatusId没有理由在现有行上进行更改。如果删除行,您的枚举就可以了,该值将永远不会被使用。您可以在进行其他维护时将其删除。

答案 2 :(得分:0)

这就是我处理它的方式。常见的场景是int,string以int作为键。将流体列表读入ctor中的Dictionary。所以我定义流体,因为他们需要重新启动应用程序以获得新的列表。

    public static Dictionary<int, string> FluidStatus { get; private set; }  // poulate in ctor
    public class FluidBus
    {
        public Int32 ID { get; set; }  // in set need error checking the ID is in range
        public String Status { get { return FluidStatus[ID]; } }  // need to check the ID is in range
        public FluidBus() { ID = 0; } // default
        public FluidBus(Int32 id) { ID = id; }
        // alternative is to pass a reference to Dictionary in the ctor as then  
        // can change out the status without changing the class
    }

实际上我主要使用它与SysName和DispName一起使用规则SysName可以没有空格。 DispName是用户看到的内容。但对于类似的XML导出,我使用SysName。这样管理员可以处理用户的想法并为他们保留一些半静态名称。

如果是程序需要使用的状态,则每次都使用Enum。在SQL方面,我将有一个不被C#使用的FK表,但作为一个常见约束,当我在SQL中时,我可以查找名称。

答案 3 :(得分:0)

我喜欢@WojtusJ的回答,无论如何还有另一种选择:

您可以创建一个状态设置页面,您可以在其中为状态情况设置具体的statusId,所以它看起来像这样:

New status:         [Select a status]
Received status:    [Select a status]
Processing status:  [Select a status]
Complete status:    [Select a status]

并且您将通过密钥存储这些设置,例如'new''received'等。然后,您可以获得statusId新订单的'new'状态继续 - 'new' statusId引用名称为Completed的状态无关紧要。