C# – What to Return with Async CRUD methods

asyncccrud

While there is a similar question focused on Java, I've been in debates with utilizing Task objects. What's the best way to handle returns on CRUD methods (and similar)?

Common returns we've seen over the years are:

  • Void (no return unless there is an exception)
  • Boolean (True on Success, False on Failure, exception on unhandled failure)
  • Int or GUID (Return the newly created objects Id, 0 or null on failure, exception on unhandled failure)
  • The updated Object (exception on failure)
  • Result Object (Object that houses the manipulated object's ID, Boolean or status field to with success or failure indicated, Exception information if there was one, etc)

The concern comes into play as we've started moving over to utilizing C# 5's Async functionality, and this brought the question up of how we should handle CRUD returns large-scale. In our systems we have a little of everything in regards to what we return, we want to make these returns standardized…

Now the question is what is the recommended standard? Is there even a recommended standard yet? (I realize we need to decide our standard, but typically we do so by looking at best practices, see if it makes sense for us and go from there, but here we're not finding much to work with)

Best Answer

After a lot of searching around the net as much as I could here's the end results I've come up with based on my research.

Things to avoid

  • Avoid using void with async methods. Voids don't pass exceptions up to the calling method which can lead to hard to debug async code. (this can be mitigated, but is still discouraged)
  • Avoid using Booleans with Create/Insert Method. returning the key is just as effective if all you care about is if it worked or not, plus there are many times you'll need that key immediately after the Create/Insert

Things to Consider

  • For all CRUD methods (except read) using a "Result Object" or "Façade Object" can make sense depending on your structure. If you take advantage of the object for stuff like error handling it can be beneficial, if not it'll probably be just a waste of time and resources.

  • Create / Insert Methods returning the key field is preferable to bool or void.

  • Update Methods returning bool is preferable to key or void if the update is a separate method, if it's an upsert treat it like an insert.

  • Delete Methods returning bool is preferable to void, key is fine, but often doesn't mistake

  • Read is a given in it should return whatever data was requested.

Personal opinion

Only use Result or Façade objects if you're going to use them for stuff like error handling, otherwise.

  • Create / Insert / Upsert : key field
  • Update : Boolean
  • Delete : Boolean
  • Read : Requested Data