Grid Editing Techniques with CSLA for Silverlight

Grid Editing Techniques with CSLA for Silverlight

Old forum URL: forums.lhotka.net/forums/t/5415.aspx


Ash002 posted on Tuesday, September 16, 2008

Hi All

We are trying to establish our grid editing basics for a new application. This is a re-engineering of a current app. Our basic edit page will populate a grid, allow editing, and then allow the user to click save when their editing is done, saving muliple rows back to the server.

The two alternatives CSLA seems to offer are: a BusinessListBase class containing child BusinessBase objects, or an EditableRootListBase containing root BusinessBase objects.

The BusinessListBase approach:
The EditableRootList approach:
What are people doing to support grid editing of a few hundred rows?

Is it possible to save only the dirty objects from an EditableRootList?

Is it possible to save only the dirty objects from a BusinessListBase?

eg Create a new instance of the list and copy in only the dirty objects?

Is this way off track?!?

Thanx in advance

Ashley


sergeyb replied on Wednesday, September 17, 2008

Just a few random thoughts….

ERLB saves as you go in Silverlight, just as it does in .NET, essentially when you switch rows.  There should not be a pause because save (like any other operation in CSLA SL) is asynchronous.  Cancelling of changes however is another story.  You have to train your users to hit Cancel to discard an edit on existing cell, and Cancel+Cancel to discard changes to all cells in current row.  This is not as intuitive of a UI as you might like for your users.  I personally think that BLB with a cancel / save buttons makes a better UI. No, it is not possible to only send dirty rows from BLB out-of-the-box.  There were a few threads on the forum that described that people wrote a code to do just that, but CSLA does not support it in itself due to data consistency concerns, etc….  You can probably do it on your own if there is a very compelling reason to do so.  I am not sure how big of a hit on memory you take.  I’d be curious to find out if you can take those measurements. 

 

Sergey Barskiy

Principal Consultant

office: 678.405.0687 | mobile: 404.388.1899

Magenic ®

Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: Ash002 [mailto:cslanet@lhotka.net]
Sent: Tuesday, September 16, 2008 11:45 PM
To: Sergey Barskiy
Subject: [CSLA .NET] Grid Editing Techniques with CSLA for Silverlight

 

Hi All

We are trying to establish our grid editing basics for a new application. This is a re-engineering of a current app. Our basic edit page will populate a grid, allow editing, and then allow the user to click save when their editing is done, saving muliple rows back to the server.

The two alternatives CSLA seems to offer are: a BusinessListBase class containing child BusinessBase objects, or an EditableRootListBase containing root BusinessBase objects.

The BusinessListBase approach:

The EditableRootList approach:

What are people doing to support grid editing of a few hundred rows?

Is it possible to save only the dirty objects from an EditableRootList?

Is it possible to save only the dirty objects from a BusinessListBase?

eg Create a new instance of the list and copy in only the dirty objects?

Is this way off track?!?

Thanx in advance

Ashley

 



ajj3085 replied on Wednesday, September 17, 2008

Ash002:
if a few hundred rows are displayed, this approach creates a large n-level undo snapshot and send a lot of data back to the server when saving, eg a few meg to save a few rows is quite an overhead.


Um, not quite.  N-level undo data doesn't transport; you MUST get your editlevel back to 0 by canceling or applying edits prior to calling save.

However, if a user only changed 5 out of 100 rows, the other 95 DO get sent back.  But the undo snapshots are NOT part of the stream.  That's ok though; the unchanged objects are still part of the parent's state, and need to be included technically.

Ash002:
Conceptually the root collection hosts no business functionality other than to list the search results, ie there are usually no rules applied across the collection itself, rather the rules are in each of the child objects.


In practice this is true, because there's no way for the collection itself to report errors back to the UI via the IDataErrorInfo interface, nor does it have broken rules.  But your rules would likely be on the child object anyway.  If you need rules across the collection, you could create a parent BusinessBase which has the collection BLB as a child, and run rules there.  This also gives you a chance to report the rules. 

Ash002:
N-Level undo is probably not required for these types of grids as refetching would suffice


Then you don't need to use n-level undo.  For a user experience that users will expect though, DataBinding will still call BeginEdit / Cancel or ApplyEdit.  You shouldn't disable that, because users won't get the expected grid behavior (namely pressing ESC to cancel changes to a row).  The binding undo behavior is handled by the n-level undo logic.

Ash002:
The EditableRootList approach:  Makes us save each row as editing is finished on the row.


Yes; ApplyEdit will cause the row to Save.

Ash002:
Saving as you go might slow down editing as there is a pause after the each row to get across the network to the database.


Yup.  It may not even be that noticable though.. but only testing in your environment will tell.

Ash002:
Conceptually perhaps better because there are usually no business rules to enforce between the objects in the list, use case for editing a list of User objects is simply to be able to update each user in isolation from the others.


That depends on the use case.  But if your use case says all the updates are done as a single batch, this isn't the way to go.  Remember, a root object is the one controlling the database transaction.

Ash002:
N Level undo would apply to each root object and so would match row editing and allow changes to a single row to be cancelled - which would be appropraite. 


The same experience would apply to the BLB root class as well.  The only difference is that ApplyEdit here will commit to the database; ApplyEdit on the BLB child will just "save" the user's changes to the row (which would only be undo-able by reloading the list, unless you do more to use n-level undo).

Ash002:
What are people doing to support grid editing of a few hundred rows?


It depends on the specific use case.  Smile [:)]

Ash002:
Is it possible to save only the dirty objects from an EditableRootList?


Well, that's what happens by default.  Since each object in the list is a root, that object goes back and forth by itself; it has no idea it's even part of a collection.  Which means you can't have rules that work "across" the collection.

Ash002:
Is it possible to save only the dirty objects from a BusinessListBase?


Yes, but the entire object graph will travel to the server in a remoting setup.  But clean objects wouldn't communicate with the database, if you code it that way.

Ash002:
eg Create a new instance of the list and copy in only the dirty objects?


You could do that, but you'd be working with the "premature optimization" anti-pattern.  Have you even tried the BLB with 100 objects to see how it performs?  There are also other ways to reduce network traffic; you could use the CompressedDataPortal, for example.  But before you do anything, I'd see how it works as-is.

Also, there's a danger when you only try to save part of the objects state; the clean objects might be necessary on the server, for example if rules need to be re-run.  If they're not there, you may get broken rules when you shouldn't, or worse, not get broken rules when you should.  You also need to worry about how to update the BLB and it's children in place, rather than just replacign the reference and rebinding the UI. 

I recommend trying to send only dirty BOs across the wire; it's not going ot make saving noticably faster, and there are many hidden dangers.

Ash002 replied on Wednesday, September 17, 2008

Hi Guys,

 

Thanks for the extensive input.

 

To summarise/clarify a little -

 

Our need is to create a UI using grids. The saving speed of 100 rows is probably ok, its the saving of 200, 300 or 500 rows which concerns me. The user will then make changes to a few rows and press a save button. The save button is required for consistency with the old app and for consistency within the new app.

 

EditableListRootBase does not, in its current form, fit with the save button, as rows are saved automatically on row exit - and it has no option to postpone saving.

 

Silverlight's async approach is cool and certainly would help with any delay occuring on row exit, but we need to use a save button for the sake of consistency as stated.

 

I understand the snapshot does not travel over the wire, so its only a single copy of the data that travels on the wire.

 

Yes this could be an anti-pattern of premature optimisation and the testing of the theory needs to be done. This application however will be sold commercially to many customers, and we can't afford to be clobbering their network with our app, and we want to be able to run over the internet. Thats the advantage of silverlight. If the option to send/recieve less data exists I would use that where appropriate.

 

You point is well taken about the risk of not sending the whole object over, and the nessecity of the clean objects on the server. There are certainly many cases where that is true. Eg form style pages which involve more complex object relationships, or a grid such as a timesheet.

 

However there are many use cases where you don't need the clean objects on the server - ie anywhere you could use an EditableListRootBase. In these cases the business objects themselves make sense as root objects, ie self contained behaviours and rules.

 

But I have now learnt that saving only the dirty objects in a single save is not an out of the box feature.

 

Many Thanks

 

Ashley

 


From: ajj3085 [mailto:cslanet@lhotka.net]
Sent: Wednesday, 17 September 2008 10:47 PM
To: Ashley Dickson
Subject: Re: [CSLA .NET] Grid Editing Techniques with CSLA for Silverlight

 

Ash002:

if a few hundred rows are displayed, this approach creates a large n-level undo snapshot and send a lot of data back to the server when saving, eg a few meg to save a few rows is quite an overhead.



Um, not quite.  N-level undo data doesn't transport; you MUST get your editlevel back to 0 by canceling or applying edits prior to calling save.

However, if a user only changed 5 out of 100 rows, the other 95 DO get sent back.  But the undo snapshots are NOT part of the stream.  That's ok though; the unchanged objects are still part of the parent's state, and need to be included technically.

Ash002:

Conceptually the root collection hosts no business functionality other than to list the search results, ie there are usually no rules applied across the collection itself, rather the rules are in each of the child objects.



In practice this is true, because there's no way for the collection itself to report errors back to the UI via the IDataErrorInfo interface, nor does it have broken rules.  But your rules would likely be on the child object anyway.  If you need rules across the collection, you could create a parent BusinessBase which has the collection BLB as a child, and run rules there.  This also gives you a chance to report the rules. 

Ash002:

N-Level undo is probably not required for these types of grids as refetching would suffice



Then you don't need to use n-level undo.  For a user experience that users will expect though, DataBinding will still call BeginEdit / Cancel or ApplyEdit.  You shouldn't disable that, because users won't get the expected grid behavior (namely pressing ESC to cancel changes to a row).  The binding undo behavior is handled by the n-level undo logic.

Ash002:

The EditableRootList approach:  Makes us save each row as editing is finished on the row.



Yes; ApplyEdit will cause the row to Save.

Ash002:

Saving as you go might slow down editing as there is a pause after the each row to get across the network to the database.



Yup.  It may not even be that noticable though.. but only testing in your environment will tell.

Ash002:

Conceptually perhaps better because there are usually no business rules to enforce between the objects in the list, use case for editing a list of User objects is simply to be able to update each user in isolation from the others.



That depends on the use case.  But if your use case says all the updates are done as a single batch, this isn't the way to go.  Remember, a root object is the one controlling the database transaction.

Ash002:

N Level undo would apply to each root object and so would match row editing and allow changes to a single row to be cancelled - which would be appropraite. 



The same experience would apply to the BLB root class as well.  The only difference is that ApplyEdit here will commit to the database; ApplyEdit on the BLB child will just "save" the user's changes to the row (which would only be undo-able by reloading the list, unless you do more to use n-level undo).

Ash002:

What are people doing to support grid editing of a few hundred rows?



It depends on the specific use case.  Smile <img src=">

Ash002:

Is it possible to save only the dirty objects from an EditableRootList?



Well, that's what happens by default.  Since each object in the list is a root, that object goes back and forth by itself; it has no idea it's even part of a collection.  Which means you can't have rules that work "across" the collection.

Ash002:

Is it possible to save only the dirty objects from a BusinessListBase?



Yes, but the entire object graph will travel to the server in a remoting setup.  But clean objects wouldn't communicate with the database, if you code it that way.

Ash002:

eg Create a new instance of the list and copy in only the dirty objects?



You could do that, but you'd be working with the "premature optimization" anti-pattern.  Have you even tried the BLB with 100 objects to see how it performs?  There are also other ways to reduce network traffic; you could use the CompressedDataPortal, for example.  But before you do anything, I'd see how it works as-is.

Also, there's a danger when you only try to save part of the objects state; the clean objects might be necessary on the server, for example if rules need to be re-run.  If they're not there, you may get broken rules when you shouldn't, or worse, not get broken rules when you should.  You also need to worry about how to update the BLB and it's children in place, rather than just replacign the reference and rebinding the UI. 

I recommend trying to send only dirty BOs across the wire; it's not going ot make saving noticably faster, and there are many hidden dangers.


ajj3085 replied on Thursday, September 18, 2008

Well, the choice to use Silverlight or not must be made up front, before you do any other work, because that choice will dictate which version of Csla.net to use. 

As far as your concerns, test and find out.  Don't do anything unless you've confirmed your fears.  While I understand you don't want to "clobber" their network, you also don't want to add unnecessary complexity.  Complexity means a harder to debug / maintain program, which means you have more risk of crashes. 

As far as complete object graphs go.. that's up to you and how you design your objects.  If your use case allows each row to be updatable independently (because one row does not in any way affect another), you could very well construct a BLB like class that only sends the dirty rows to update.  Like you said, this isn't out of the box, but shouldn't be too difficult either. 

Ash002 replied on Thursday, September 18, 2008

The choice to use Silverlight has been made and we have been working with Silverlight and Csla for Silverlight a few months now.

 

You are right to point out that we need to do the experiment however. The amount of data which produces an acceptable load time, would probably result in an acceptable save time. We could just provide an option to set the results size, and users could set according to their situation.

 

As to making an arrangement to save only the dirty data, I would be more inclined to use EditableRootListBase than BLB. ERLB seems to be the result of the thinking involved in the Csla paradigm. Ie root objects travel on their own, child objects travel with the root. So ERLB not sending the updated objects until a save button click, and then sending all the saved objects, seems to be in keeping with csla principles. A BLB with missing child objects, seem to be outside of those principles.

 

In the case where there are business rules across the grids rows, then the BLB arrangement would be the right choice. But in those cases I wouldn’t be inclined to optimise and send back only dirty data. As that creeps into risky territory. I think ERLB would cover most circumstance and keep it simple as you say.

 

Actually this idea seems a natural extension to ERLB. The principle being that the objects’ only business relationships with each other is that they happen to be on the same grid. In that sense ERLB is a view technology.

 

That said I have played with overriding ERLB. Postponing saves is easy. I then create “copies” ERLB, legitimate as ERLB is just view/collection of BOs. Then clone each dirty or deleted BO, add to “copies” and pass copies to DataPortal Update(). On the server side call SaveItem() for each item in copies. All seems too damn simple. There is the issue of getting the objects back into the original ERLB, with new IDs etc, and checking to make sure Clone() is a deep clone (I am kinda assumming that as Clone is essential to Csla and its snap shots etc).

 

Will see how iit all goes.

 

 

RockfordLhotka replied on Friday, September 19, 2008

Ash002:

In the case where there are business rules across the grids rows, then the BLB arrangement would be the right choice. But in those cases I wouldn’t be inclined to optimise and send back only dirty data. As that creeps into risky territory. I think ERLB would cover most circumstance and keep it simple as you say.

If you really want to only transfer datagrams, not object graphs, you should consider using the local data portal and calling your own custom WCF services that return/consume datagrams. That may be a simpler overall solution.

Yes, you give up the mobile object features of the data portal, but it sounds like you really don't want them anyway (mobile objects and datagrams are different models).

Ash002 replied on Friday, September 19, 2008

Hi Rocky

Hhmmm...

Well I don't think I am thinking that its just about transfering data graphs, but I'll give it some thought. That would be a client server arrangement with a Silverlight client.

Whats on my mind is using the validity of EditableRootListBase. Root objects travel to client, root object is changed, root object goes to server. I am told the screens could require the flexibility to be able to load a largish amount of rows for perusal by the user, and we want to use a save button. This seems a natural extension to ERLB, ie is conceptually consistent with the "Rootness", autonomy, of the objects in the collection.

When a screen is not consistent with ERLB, ie rules across child BOs, then using BLB as it stands is the right approach and gives the advantages of mobile objects. BLB screens may need a smaller limit on the amount of data the retrieve, which is fine.

Anyway will think on it, and the nessecity.


RockfordLhotka replied on Friday, September 19, 2008

That is true, ERLB does coordinate autonomous root objects. And if you user’s are good with that experience (no cancel button, etc) then it is a great option!

 

BLB is a good option too – for the same scenarios, but with different user expectations around when things commit and can be canceled.

 

But if you want BLB semantics, and only want to transfer changed data (which I thought was discussed earlier in the thread), then you enter the realm of datagrams. CSLA doesn’t do that, because it provides an inconsistent object model and context on the client and server. Not that that’s always bad, but it is outside the goals for the data portal, which is all about providing a consistent object model and context on both sides of the wire.

 

Which is why you have the option of using the local data portal (globally, or for specific objects), in case you want datagram semantics in certain (or all) scenarios.

 

I’m not trying to push you one way or another – just trying to compartmentalize the concepts and their application.

 

The real world is full of gray areas. But gray areas waste time and money, so personally I always force gray areas into one box or another. Much like Stephen Colbert’s attitude (to paraphrase): mobile objects or datagrams, pick a side! :)

 

Rocky

 

Ash002 replied on Monday, September 22, 2008

Hi Rocky

 

I am glad you have been talking about releasing Csla material which covers a wider range because that would help us know how Clsa is being used. I know it must seem logical when you already know it.

 

We don’t just want to send changed data, that’s just one possible solution. “Use case” is Silverlight client with an internet connection to the DB. An ADSL 1 connection for example has pretty slow upload speed, but ok download speed. Necessity: an example grid had over 11meg of serialised mobile objects when loading 1400 rows. With only an moderate amount of columns. So 200 rows = 1.5 meg. That’s still quite a download over the net. For a save its 1.5 meg up and 1.5 meg down.

 

We want the object model too, and the mobile objects.

 

Paul has done some quick work in compressing the data portal transfers in the Silverlight data portal with good results. We could apply compression once a threshhold size is reached. So we will see how this goes and start off using vanilla BLBs.

 

Thanks for your input.

 




Copyright (c) Marimer LLC