简体   繁体   English

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

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

I am wondering how people handle the following scenario (this is hypothetical to get the idea across)... 我想知道人们如何处理以下情况(这是使想法传播的假设)...

  • TABLE A (Orders): OrderId, StatusId , etc (foreign key on status table) TABLE A (Orders): OrderId, StatusId等(状态表上的外键)
  • TABLE B (Statuses): StatusId, Name, etc TABLE B (Statuses): StatusId, Name,

Table B Needs to exist (IOW, I can't just create an enum of statuses for example), because the order status list needs to be dynamic as business needs and practices change and you have methods in your program like GetAllOrders() , GetAllStatuses() , GetOrderByStatus(int statusId) , etc. However, it seems like you continually need to access a "hard coded" status. 表B需要存在(IOW,我不能仅创建一个状态枚举),因为随着业务需求和实践的变化,订单状态列表必须是动态的,并且程序中有诸如GetAllOrders()GetAllStatuses()GetOrderByStatus(int statusId)等。但是,似乎您不断需要访问“硬编码”状态。 For example, when an order is first created it's status is "New" and you need to set it to that status without any user intervention. 例如,第一次创建订单时,其状态为“新建”,您需要在没有任何用户干预的情况下将其设置为该状态。 Perhaps you have a GetUnfilledOrders report that returns all orders that are "processing", again without having the user select the status they're looking for because the name of the report implies what they want. 也许您有一个GetUnfilledOrders报表,该报表返回所有“正在处理”的订单,而又没有让用户选择他们要查找的状态,因为报表的名称暗示了他们想要的。 I hope you get the idea. 希望您能明白。

What I've been doing in these cases is creating a setting such as DefaultNewOrderStatus (int) and setting it to the id of the status I'd like to use for new orders, or StatusesForUnfilledOrdersReport (int[]) and again setting a list of statuses to use. 在这些情况下,我一直在做的事情是创建一个诸如DefaultNewOrderStatus (int)设置,并将其设置为我想用于新订单的状态的ID,或者将其设置为StatusesForUnfilledOrdersReport (int[])然后再次设置一个列表使用的状态。 The idea being that I can change these settings on the fly if our status "architecture" changes. 我的想法是,如果我们的状态“体系结构”发生更改,我可以即时更改这些设置。 The issue is that the number of "hard coded" values needing to be used seems to grow (maybe now I need a default status to set fulfilled orders to, or a list of statuses to use to display an "Open" orders UI view, etc) and along with it, so do the number of settings to handle them. 问题在于,需要使用的“硬编码”值的数量似乎正在增加(也许现在我需要使用默认状态来设置已履行的订单,或者需要使用状态列表来显示“未结”订单UI视图,等等),以及要处理这些设置的数量。

I'm extremely interested in knowing how others out there handle these situations? 我非常想知道其他人如何处理这些情况?

I'm not sure if I caught the point of your question, but it looks like you are trying to implement Business Process Manager in a "Hard coded" way. 我不确定是否抓住了您的问题,但是您似乎正在尝试以“硬编码”方式实现Business Process Manager。 What you actually need is not a dynamic list of statuses, but dynamic list of processes which are in fact scenarios of how to use statuses. 您实际需要的不是状态的动态列表,而是过程的动态列表,实际上是有关如何使用状态的方案。 Additionally you need actions, which will trigger statuses change. 此外,您还需要采取措施来触发状态更改。 So, lets take for example, you have a list of statuses: 因此,举个例子,您有一个状态列表:

  1. NEW
  2. PROCESSING 处理
  3. DELIVERY 交货
  4. FINISHED FINISHED

Next, a list of actions: 接下来,列出动作:

  1. CREATE NEW 创建新的
  2. START PROCESSING 开始处理
  3. GO INTO DELIVERY 送货上门
  4. FINISH DELIVERY 完成交货
  5. RETURNED 回来

Now, you can design a process: 现在,您可以设计一个流程:

  • [START] -> (CREATE NEW) -> NEW [开始]->(创建新内容)->新
  • NEW -> (START PROCESSING) -> PROCESSING 新建->(开始处理)->处理
  • PROCESSING -> (GO INTO DELIVERY) -> DELIVERY 处理->(进入交货)->交货
  • DELIVERY -> (RETURNED) -> PROCESSING 交付->(返回)->处理
  • DELIVERY -> (FINISH DELIVERY) -> FINISHED 交付->(完成交付)->完成

Your application needs to have a set of methods which can operate upon the above (forms usually, some wizards, etc.). 您的应用程序需要具有一组可以对上述方法进行操作的方法(通常是窗体,某些向导等)。 When something changes, you add new statuses, copy and modify the process and your application already know how to deal with it, for example you need to deal with cancellation of your order. 发生变化时,您可以添加新状态,复制和修改流程,并且您的应用程序已经知道如何处理该流程,例如,您需要处理订单的取消。 You add CANCEL to your actions, CANCELLED to your orders and create new process (or modify the old one) adding: 您将“取消”添加到您的操作中,将“取消”添加到您的订单中并创建新流程(或修改旧流程)并添加:

  • PROCESSING -> (CANCEL) -> CANCELLED 处理->(取消)->取消

So, to sum up, your problem is not the status change only, but the change in a business process. 因此,总而言之,您的问题不只是状态更改,而是业务流程中的更改。 In that case you need to have dynamic processes, not only statuses. 在这种情况下,您不仅需要状态,还需要动态过程。 Than, the problem disappears - but you need to rebuild your application- or rather build a new application. 然后,问题消失了-但是您需要重新构建应用程序-或更确切地说是构建新的应用程序。

EDIT 编辑

Regarding the reports, it's a rather different situation. 关于报告,情况截然不同。 If you find a way to prepare generic architecture that is capable of generating any report you will be reach as you will challenge the actual form of Business Intelligence, data warehousing concept, etc. :-) 如果您找到一种能够生成任何报告的通用体系结构的方法,那么您将面临挑战商业智能,数据仓库概念等的实际形式:-)

Make the Enum. 进行枚举。 This enum is for your business logic. 该枚举用于您的业务逻辑。 You can still present the list of available status from the database query. 您仍然可以从数据库查询中显示可用状态列表。

When you convert the StatusId to an StatusEnum value, you will need to have a case for a new value in the database. 当您将StatusId转换为StatusEnum值时,将需要为数据库中的新值指定大小写。 However, all of your logic should be fine, because New will still be New. 但是,您的所有逻辑都应该没问题,因为“新建”仍然是“新建”。 If you need to write logic that uses a newly created status, update the Enum. 如果您需要编写使用新创建状态的逻辑,请更新Enum。

For something like a status, there is no reason the StatusId should ever change on an existing row. 对于类似状态的情况,没有理由在现有行上更改StatusId。 If rows are removed, your Enum is fine, that value will just never be used. 如果删除了行,则枚举就可以了,该值将永远不会被使用。 You can remove it when you are doing some other maintenance. 您可以在进行其他维护时将其删除。

This is how I handle it. 这就是我的处理方式。 The common scenario is int, string with int as a key. 常见的情况是int,以int为键的字符串。 Read the fluid list into a Dictionary in ctor. 将流体列表读入ctor词典中。 So I define fluid as they need to restart the app to get a fresh list. 因此,我定义了流畅性,因为他们需要重新启动应用程序才能获得新列表。

    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
    }

Actually I mainly use it with SysName and DispName with a rule SysName can have no spaces. 实际上,我主要将它与SysName和DispName一起使用,并且SysName不能有空格。 DispName is what the user sees. 用户看到的是DispName。 But for like XML export I use SysName. 但是对于XML导出,我使用SysName。 That way admin people can deal with the user whims and keep some some semi static names for them. 这样,管理员可以处理用户的想法,并为其保留一些半静态名称。

If it is a status the program needs to use then Enum every time. 如果是这种状态,则程序需要每次使用Enum。 On the SQL side I will have a FK table not used by C# but as a common constraint and for when I am in SQL I can look up the name. 在SQL方面,我将有一个FK表,C#不会使用它,但它是一个常见的约束,当我使用SQL时,我可以查找名称。

I like @WojtusJ answer, anyway there is also another option: 我喜欢@WojtusJ答案,无论如何,还有另一个选择:

You can create a status settings page where You will be able to set a concrete statusId for status situation, so it would look like this: 您可以创建一个状态设置页面,在其中可以为状态情况设置一个具体的statusId ,因此如下所示:

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

And You will store these settings by a key, like 'new' , 'received' , etc. Then You can get the statusId of the 'new' status for new order and continue - does not matter that 'new' statusId reffers to status with name Completed . 然后,您将通过密钥存储这些设置,例如'new''received'等。然后您可以获取新订单的'new'状态的statusId并继续-无关紧要'new' statusId转换为status名称为Completed

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

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