views:

260

answers:

3

For a clean data model, I'm going back and forth on this...

Using an approval workflow as an example, let's say in my web application I have a page that lets a user flag a MyEntityObject for approval. MyEntityObject has a few properties that control its approval workflow, so I have a common utility method out there called FlagForApproval(MyEntityObject eo).

Should the page call FlagForApproval() to set necessary properties only and then call SaveChanges() when it's ready, or should FlagForApproval() save the changes?

Having the utility method save changes seems like it's doing a little more than it's asked to do (what if it was just one step in a series of operations?), but at the same time, making the page call SaveChanges() and commit the data to the DB seems like it could be considered too close to data layer responsibilities.

Thoughts?

(Update: FWIW, so far I have been having utility methods call SaveChanges(), that way the page only has one set of exceptions to handle, whether validation or data.)

+2  A: 

My current opinion on this issue is to always have the business logic layer call save changes after validating data. When the user clicks Save button, i pass whatever entities need to be validated down to the BLL, and it decides whether to SaveChanges().

I'm as curious as you though, to see what others say because this issue (and many other) has been plaguing me since i started with EF.

echo
I think you're 100% right - it's very clean to keep SaveChanges in BLL and let it decide whether to perform save or not. But I can see at least 2 situations, where an exception can be made:1) The project requires validation on the Model side - it's not BLL, but it has to decide if changes should be saved or not.2) SaveChanges is executed after really simple code (adding an entity, updating single properties of an existing entity). In my case it would be DAL. So I guess the best solution is to follow your instinct and/or experience.
Piotr Justyna
A: 

I'm not sure there is a right or wrong answer, but it feels cleaner (imo) to have FlagForApproval handle the process for starting the workflow. That includes telling the DataLayer to persist the state of the object (i.e. SaveChanges). However this assumes that you have business requirements stating that once a workflow is started the state should be persisted so if something happens (i.e. server crashes) the workflow process continues from last step.

JD
+1  A: 

The key is to separate Database and Service language. If the utility method needs to save changes then it does, if not make it clear that it does not and additional steps are needed. The utility should not have a method called SaveChanges, it should have process related methods, like StartProcess or LoadToBatch.

View the utility as more of a service and do not think database. The "FlagForApproval" sounds like a database operation, try thinking of the method as something like "StartApprovalProcess" or something else process related. StartApprovalProcess would do all work and commits.

If there are multiple steps, make each step indicate indirectly that there may be more steps. Only the last step commits. Allthough all the last step may do is save changes, make is read like a process such as move or start.

Ex:

  1. LoadToBatchApproval(MyEntityObject eo)

  2. ValidateApprovalBatch()...

  3. MoveBatchToProcessing()...