3

I am trying to implement the Repository pattern. I have a doubt where let's say we are trying to perform an update on a record that does not exist. In this case should we throw an exception? If yes, should we throw ArgumentException or InvalidOperationException?

In case of ArgumentException, the input isn't valid. but the input can be valid and still the record won't exist. so should we throw InvalidOperationException as we are trying to perform an operation on a resource that does not exist?

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • It's up to you to throw or not to throw. As for which exception to throw see [this duplicate](https://stackoverflow.com/q/16434842/1997232). – Sinatr May 04 '21 at 09:33

1 Answers1

1

In order to answer a question like this, I try to start by imagining what might cause such a situation to happen in the first place.

If you have an update that affects no rows, it could be caused by one of these situations:

  • In a concurrent system, the record may have existed when the update was issued, but another, concurrent operation deleted it before it hit the database. In an optimistic locking scenario, the time frames involved can easily be minutes, so this isn't nearly as unlikely as it sounds.
  • The programmer calling the update procedure made a mistake.

In both cases, I think that the caller would like to learn that the operation failed. Clients call lower-level code with some intent. Here, the intent is to update the record. If the update doesn't take place, then the lower-level code failed to carry out the intent. This can happen, but should be signalled back to the caller. While it's technically possible to just ignore such situations, many bugs could hide behind such behaviour.

In short: Throw an exception.

Specifically, throw an InvalidOperationException. As the documentation states:

InvalidOperationException is used in cases when the failure to invoke a method is caused by reasons other than invalid arguments. Typically, it is thrown when the state of an object cannot support the method call.

It's true that a bug could make calling code invoke the method with a non-existing record, in which case you could argue that the problem is the argument, and not the state of the system.

Bugs, however, should be fixed. Even if such a bug exists, once you've addressed it, it's gone, and you'll have no more invalid arguments. Thus, while concurrency is a reality you have to deal with, invalid arguments shouldn't be observed as long as no bugs exist.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736