views:

162

answers:

4

So I'm comfortable with the basic concept of CQS, where you might have a command that writes to one database, and that updates the query database that you read from.

However, consider the scenario where you are entering data, and want to prevent duplicates.

Using new employee data entry an employee register as an example, working through a pile of application forms to key in the new employees' details:

  1. Take top sheet.
  2. Key in employee name and unique payroll number to UI.
  3. Submit.
  4. Put paper in "completed pile".
  5. Repeat.

How would you now prevent the user from keying in the same payroll number again, say for instance if they get distracted and can't remember whether they've keyed one in already and the "message" hasn't got all the way back to the query db for the user to search?

A: 

I suggest to change the workflow to this

  1. Check the top sheet is taken or not in database (you should have a table R to remember whether the specific row is taken or not), if taken then return false if not, then Take top sheet. and set the flag for the taken row to be "taken" in table R
  2. Key in employee name and unique payroll number to UI.
  3. Submit.
  4. Put paper in "completed pile".
  5. Repeat.

The step should be execute atomically.

sza
But that's exactly the process I've described - the question is on your step 1 - how do you know you haven't just submitted the top sheet, if you're checking before the message has updated the query db?
Neil Barnwell
Because you can limit the retrieval. When the user retrieved the top entry, you marked it as "taken", which means only 1 client got that.
sza
A: 

Could you keep track of a list of already entered employee/payroll number combos on the client? If this is a web client, could be a cookie, if a thick client, then memory or otherwise. When they enter the system for the first time, clear the list and start anew.

Adam Fyles
A: 

Data entry is a non-collaborative domain - you don't have multiple users performing actions on the same shared set of data. As such, CQRS isn't particularly relevant.

Udi Dahan
My problem isn't with multiple users, it's about the same user submitting the same thing twice. I can't rely on querying the database to prevent them doing it, because the data might not be in the database in time.
Neil Barnwell
What I'm saying is that you shouldn't use one-way commands (a la CQRS) for this - do it fully synchronous all the way through to the DB. Keep it simple :)
Udi Dahan
+1  A: 

First off you can easily use a local cache to make sure the immediate user does not re-use the same numbers again. That's easy enough.

But really this doesn't stop the fact that by mistake two people can use the same critical piece of data at the same time. As someone else mentioned though this is outside of CQRS. This could happen in almost any architecture.

Now the main thing that CQRS could change is how we respond to a conflict. I see two possible solutions:

  1. The system sends the command off and then waits for a successful result. If it's a failure you just ask for fixed information and try again. From everything I've heard this seems wrong and might even be an anti-pattern though I'm no where near expert enough to say either way.

  2. The system sends the command off and eventually the user is informed about the conflict. There is somewhere they can go to fix the problem. In your case by entering a new number (which could again conflict).

ShaneC