简体   繁体   中英

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 B (Statuses): StatusId, Name, etc

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. 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. 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. 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.

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. 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

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. 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.

For something like a status, there is no reason the StatusId should ever change on an existing row. 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. Read the fluid list into a Dictionary in 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. DispName is what the user sees. But for like XML export I use 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. 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.

I like @WojtusJ answer, anyway there is also another option:

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:

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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