New Posts New Posts RSS Feed: Unit of Work Pattern
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Unit of Work Pattern

 Post Reply Post Reply
Author
SirSmackalot View Drop Down
Newbie
Newbie


Joined: 22-Oct-2012
Posts: 4
Post Options Post Options   Quote SirSmackalot Quote  Post ReplyReply Direct Link To This Post Topic: Unit of Work Pattern
    Posted: 22-Oct-2012 at 12:33am
Hi there,

breeze is exactly what i was looking for for my project, nicely done!

I am quite new to EF, kind of following John Papas course to build my own page. He implemented the Unit of Work-Pattern on the server side. Is there an intelligent way to integrate the EFContextProvider in this pattern or is it obsolete for Breeze?

Any hint much appreciated :)


Back to Top
jagerm View Drop Down
Newbie
Newbie


Joined: 22-Oct-2012
Posts: 1
Post Options Post Options   Quote jagerm Quote  Post ReplyReply Direct Link To This Post Posted: 22-Oct-2012 at 8:35am
I have the exact same question.  I do not feel comfortable exposing my DbContext directly over Web API via OData.  I need to know how to add some separation of concerns so I can easily manage row level security.  In John Papa's example how would one ensure with Breeze that Session descriptions can only be modified by the Speaker and other row level security without writing every security rule in BeforeSaveEntity; which would end up as an unmanageable mess for larger applications.  If we could extend the Unit of Work Pattern somehow this would be ideal.  I've been looking at this for a day or so and can't seem to come up with an elegant solution.  EFContextProvider attaches records directly to the ObjectContext and calls ObjectContext.SaveChanges(AcceptAllChanges) which seems to imply that Unit of Work won't work...
Back to Top
pawel View Drop Down
Newbie
Newbie
Avatar

Joined: 21-Sep-2012
Posts: 12
Post Options Post Options   Quote pawel Quote  Post ReplyReply Direct Link To This Post Posted: 22-Oct-2012 at 11:27am
Back to Top
WardBell View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Mar-2009
Location: Emeryville, CA,
Posts: 338
Post Options Post Options   Quote WardBell Quote  Post ReplyReply Direct Link To This Post Posted: 22-Oct-2012 at 5:22pm
By all means vote those two up! 

Meanwhile, I think you have a choice today that is not as terrible as you see it.

Extract the EFContextProvider

First, you can pull the EFContextProvider out of the controller and wrap it in your own UoW component. It would take about two minutes to create "MyUoW", move EFContextProvider inside it, and have your WebApi controller methods delegate to MyUoW in exactly the same way they now call EFContextProvider. Use Web API dependency injection to get it into your controller instances just like John does in CodeCamper (CC).

This is not substantively different than CC. Of course we're just moving the pea from under one cup to under another.

Dispatch validations by type

@jagerm's concerns are an opportunity to make MyUoW carry its own weight. I wouldn't write a BeforeSaveEntity method for each type.  I doubt I would ever use this method. I guess it's OK for a tiny model but not a medium-sized model and it's just wrong architecturally IMO. The UoW shouldn't know details like this for each type. 

Instead, I'd want the UoW act as a dispatcher (or maybe delegate to a dispatcher)* in a BeforeSaveEntities (plural) method (see http://www.breezejs.com/documentation/server-side-interception).

  *the UoW either inherits from EFContextProvider and override BeforeSaveEntities or can delegate to a component that does.

The BeforeSaveEntities method receives a dictionary of types, each entry being a list of entities of that type that are to be saved. For each type it looks for a corresponding "save validation components". These are separate classes that are either registered or discovered during service initialization. Your BeforeSaveEntities dispatches its arguments* to each of these components in turn. You get the idea.

* make sure to pass the entire SaveMap in your protocol; sometimes a save validation component needs to know what else is being saved with it; think about an order and its orderdetails.

The point is that no one class tries to do too much. The Controller stays thin because it talks to the injected MyUoW. The MyUoW stays thin because it dispatches saving chores to type-focused validation components that know what to do with entities of their dedicated type. Turtles all the way down.

This dispatching is not materially different than what you'd get if you had controllers-per-type. It does put dispatching under your control which, depending on your perspective, is either a good thing or a bad thing (I like it personally).

@jagerm - does this meet your need? If not why not?

And now ... a rant from me ... to encourage you to vote for a feature dear to my heart.

Why Named Saves?

From my perspective, what is missing from the above serviceable approach .. and it's missing from CodeCamper and every other Web API example I've seen ... is the ability to differentiate save requests semantically

For example, per my app's business rules it may be important for me to have a SaveNewOrder command. The only entities to be saved in such a command should be a single new order and the new orderdetails associated with that one order. The save bundle should not contain a new customer or a changed customer or orders for other customers or order details for a different order. If I see any of these entities in the bundle, it's an invalid command that I should reject on sight.

Then I have an UpdateCustomer command with similar rules governing both the contents of the save bundle and what kinds of changes are allowed.

We're no longer talking CRUD. We're talking commands with messages. The upside is close attention to the semantics of each save. The downside is close attention to the semantics of each save  :)   because you signed up to write and maintain a ton of commands!   I suspect that developers under real deadlines will take a hybrid approach, writing commands for sensitive entity types and using the "SaveChanges" command for all other types; the "SaveChanges" interceptor would disallow attempts to save Customer, Order, OrderDetails but would allow other harmless types to go through the dispatching logic described above.  This is my vision.

Now you could hack your way to this beautiful world today with a single SaveChanges method and its dispatcher. For example, you could include in the save payload (inside the save bundle) a pseudo-entity called "SaveCommand". The dispatcher detects this SaveCommand entity (which is never actually saved) and redirects to the appropriate save handler based on the value of that command.

But it's a hack. I want to write clear controller methods. I'd like to be able to decorate them with security attributes.  I might want pre- and post-save actions that don't involve persistence (e.g., send a message). 

Most importantly, I want someone reading the controller code to know what is going on! I don't want them to spelunk a dispatching table. If you agree, vote up "Named Save"

That's the end of my rant on this subject. 
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down