繁体   English   中英

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

[英]Best Practices Retrieving “Hard” Values From Relational Database

我想知道人们如何处理以下情况(这是使想法传播的假设)...

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

表B需要存在(IOW,我不能仅创建一个状态枚举),因为随着业务需求和实践的变化,订单状态列表必须是动态的,并且程序中有诸如GetAllOrders()GetAllStatuses()GetOrderByStatus(int statusId)等。但是,似乎您不断需要访问“硬编码”状态。 例如,第一次创建订单时,其状态为“新建”,您需要在没有任何用户干预的情况下将其设置为该状态。 也许您有一个GetUnfilledOrders报表,该报表返回所有“正在处理”的订单,而又没有让用户选择他们要查找的状态,因为报表的名称暗示了他们想要的。 希望您能明白。

在这些情况下,我一直在做的事情是创建一个诸如DefaultNewOrderStatus (int)设置,并将其设置为我想用于新订单的状态的ID,或者将其设置为StatusesForUnfilledOrdersReport (int[])然后再次设置一个列表使用的状态。 我的想法是,如果我们的状态“体系结构”发生更改,我可以即时更改这些设置。 问题在于,需要使用的“硬编码”值的数量似乎正在增加(也许现在我需要使用默认状态来设置已履行的订单,或者需要使用状态列表来显示“未结”订单UI视图,等等),以及要处理这些设置的数量。

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

我不确定是否抓住了您的问题,但是您似乎正在尝试以“硬编码”方式实现Business Process Manager。 您实际需要的不是状态的动态列表,而是过程的动态列表,实际上是有关如何使用状态的方案。 此外,您还需要采取措施来触发状态更改。 因此,举个例子,您有一个状态列表:

  1. 处理
  2. 交货
  3. FINISHED

接下来,列出动作:

  1. 创建新的
  2. 开始处理
  3. 送货上门
  4. 完成交货
  5. 回来

现在,您可以设计一个流程:

  • [开始]->(创建新内容)->新
  • 新建->(开始处理)->处理
  • 处理->(进入交货)->交货
  • 交付->(返回)->处理
  • 交付->(完成交付)->完成

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

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

因此,总而言之,您的问题不只是状态更改,而是业务流程中的更改。 在这种情况下,您不仅需要状态,还需要动态过程。 然后,问题消失了-但是您需要重新构建应用程序-或更确切地说是构建新的应用程序。

编辑

关于报告,情况截然不同。 如果您找到一种能够生成任何报告的通用体系结构的方法,那么您将面临挑战商业智能,数据仓库概念等的实际形式:-)

进行枚举。 该枚举用于您的业务逻辑。 您仍然可以从数据库查询中显示可用状态列表。

当您将StatusId转换为StatusEnum值时,将需要为数据库中的新值指定大小写。 但是,您的所有逻辑都应该没问题,因为“新建”仍然是“新建”。 如果您需要编写使用新创建状态的逻辑,请更新Enum。

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

这就是我的处理方式。 常见的情况是int,以int为键的字符串。 将流体列表读入ctor词典中。 因此,我定义了流畅性,因为他们需要重新启动应用程序才能获得新列表。

    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方面,我将有一个FK表,C#不会使用它,但它是一个常见的约束,当我使用SQL时,我可以查找名称。

我喜欢@WojtusJ答案,无论如何,还有另一个选择:

您可以创建一个状态设置页面,在其中可以为状态情况设置一个具体的statusId ,因此如下所示:

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

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

暂无
暂无

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

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