Porting the MVC Music Store to Raven: ShoppingCartController

The ShoppingCartController is heavily affected by the changes we made to the ShoppingCart. Let us look at those changes, starting from Index():

image image

On the left, we have the original version. You can see that it executes two different queries to process this order, the Raven version, however, is executing only a single query, in the FindShoppingCart method:

image

This just implements the logic of loading the cart from Raven or creating a new cart (with the specified shopping cart id), note that we don’t save the new cart to the database here, merely associate the new cart with the session. There is no need to save, since it contains no meaningful data at this point. When we will call SaveChanges(), the new cart will be send to Raven for storage.

Let us look at the AddToCart action now:

image  image

On the left, you can see the old version, and on the right, you see the Raven version. They are pretty similar, except that in the Raven case, the shopping cart’s AddToCart is concerned solely with adding a new item to the cart or incrementing the quantity of an existing item. There is absolutely no data access in the Raven’s version of ShoppingCart.AddToCart.

One major difference is that the Raven approach is calling the session.SaveChanges() in the action code. The reason for that is simple, it is the proper place for this, as the calling code, it is responsible for the environment, including saving when needed.

image image

Raven’s code is pretty easy to follow here, I think. There is just one thing that you should note, the last line is pretty strange id.Split ? Why do we do that?

The reason for that is that Raven uses id that looks like this: “albums/616” and the DeleteId is used by the calling javascript code to find an element by its id. An element can’t contain a ‘/’ in it, so we strip it away and only send the number part of the id. This is safe to do since we only deal with albums here.

image image

Again, this is about as simple as you can make it, so I’ll note only that Raven’s approach can benefit from the unit of work cache, and the old code approach can’t.

In my next post, we will deal with the order process.

Print | posted on Thursday, May 27, 2010 6:36 PM

Feedback


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 6:57 PM David Thibault

I believe that shoppingCart.Lines.Count should be shoppingCart.Lines.Sum(x => x.Quantity)

However I did not look at the original code so it may be correct.


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 7:21 PM Jason Meckley

an approach I use with controller's is post-redirect-get for commands. by managing transactions (SaveChanges) from a Filter there is no need to call session.SaveChanges() in the action. you also avoid the "resend post data" if the user refreshes the page.

in this series you are only porting the data access, so keeping the controllers as similar as possible makes sense.

What are your thoughts?


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 7:40 PM josh

@David Depends on what you are intending to show. The line count or the total item count.


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 9:16 PM Michael Teper

Wouldn't session.Load(id) call be data access?


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 9:17 PM Michael Teper

Ugn, subtext ate the generic part. Here's what I meant:
Wouldn't session.Load<Album>(id) call be data access?


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 9:49 PM Kiliman

@Michael, I believe he's means the ShoppingCart model does not include any data access code.

See his previous post: ayende.com/.../...store-to-raven-shoppingcart.aspx

The calling code, in this case the controller, is responsible for loading and persisting the model.

I suppose you could add another level of abstraction by introducing a ShoppingCartService that managed the data access instead of the controller, but for a simple application, this is probably overkill.


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 9:51 PM Ayende Rahien

David,
You are correct


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 9:51 PM Kiliman

@Michael, I believe he's means the ShoppingCart model does not include any data access code.

See his previous post: "Porting the MVC Music Store to Raven: ShoppingCart" (sorry, edited due to link being consider spam.. ugh!)

The calling code, in this case the controller, is responsible for loading and persisting the model.

I suppose you could add another level of abstraction by introducing a ShoppingCartService that managed the data access instead of the controller, but for a simple application, this is probably overkill.


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 9:52 PM Ayende Rahien

Json,
Post/redirect/get is much better option, sure.


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 9:53 PM Ayende Rahien

Michael,
Sure it is, but it is not in the shopping cart code


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 9:53 PM Kiliman

Oops... sorry for the double post. I didn't expect Ayende to moderate my comment so quickly. Thanks!


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 9:56 PM Michael Teper

Ayende, Kiliman, you are both right, I missed the ShoppingCart reference. Thanks!


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/27/2010 10:06 PM Harry Steinhilber

@Michael,
The point was that ShoppingCart.AddToCart() does not contain any data access. The data access is in the ShoppingCartController.AddToCart(). In the original version, the data access was in the business object instead of the controller.


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/28/2010 12:36 AM Michel

For the DeleteId value, HTML id can't start with a number (http://validator.w3.org/docs/errors.html#ve-122). So instead of returning the number part of the id, you should return the full id minus the "/" : DeleteId = id.Replace('/', string.Empty)


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/30/2010 6:33 PM Michael Valenty

Why would you prefer cart.Lines.Count over cart.GetCount()? cart.Lines.Count is a Law of Demeter violation. You don't encapsulate the logic that @David pointed out should actually be cart.Sum(x => x.Quantity). Maybe it should be a property to suggest it's not an expensive operation, but it seems like it's something the cart should own.


Gravatar

# re: Porting the MVC Music Store to Raven: ShoppingCartController 5/30/2010 8:26 PM Ayende Rahien

cart.GetCount() was a database query, _very_ expensive.
I don't care about the actual impl detail, I care about whatever this is an in memory operation or a remote operation

Comments have been closed on this topic.