Our project is using CSLA 4 and CodeSmith to generate. The task I have to solve is for a list of editable objects that can be used in a multi user situation. Each user will see the same list; however any one item will only be edited by one user. i.e. list of tasks to complete and each user of the system will only update his/her task. BUT, the UI will not do auto-saves on exit of the row. There will be a specific save button.
Somewhere on this forum, I thought I read that I should use a Dynamic List/ Dynamic Root if auto save is expected as a user leaves a row and otherwise to use the EditableRootList/EditableChild, but I can't seem to find that again.
So I created an EditableRootList with EditableChild items. But when the save is called on the EditableRootList, the code fails in the DataPortal_Update() method of the list in the For index As Integer = 0 to Items.Count -1 block on the .Save() call. It states that a child cannot be directly saved.
So, the real question is what CSLA object set do I use if I want to save individual objects in a list but not necessarily as a user leaves the focus of a row. Of course, the other users in the system will need to update their lists too without concurrency check failures (unless they do actually change a child object someone else is working on).
I ran into the first time I've ever needed to use an editable root list just recently (using a dynamiclistbase descendent). I may be wrong but you might be mixing concepts - you refer to an EditableRootList but it almost sounds like you're using child objects (you refer to EditableChild).
When fetching an editablerootlist, my understanding is that you're wanting the root list to basically do the fetch for the entire list - so you're either passing dto's or a datareader into a factory method of the editable roots in the list and then adding the editable roots to the collection. You don't want to do a FetchChild in the factory method for the editable roots, as that will mark them as children - it sounds like your items in your collection are children and you're trying to save them individually.
Child objects get saved through a child update that occurs when you save their parent, you can't call Save() on them directly. Root objects, of course, you do call save on them.
Hopefully I didn't misunderstand your question and state things you already knew.
A dynamic list contains root objects, not child objects. Each root object is saved automatically as the user changes focus off the row in the datagrid. The dynamic list base class detects the data binding notification telling it that the user has moved off the row and it updates that specific root object. Each individual root object is saved individually, not as a batch.
A normal business list contains child objects, not root objects. The items in a list are saved when the list is saved with an explicit call to Save on the list. The child objects are saved as a batch - all at once.
You did not misunderstand and when I first read the post that indicated that I needed to mix Editable Root List and Editable Child, I was surprised, but I have learned that CSLA sometimes has surprising things and have mostly stopped questioning "why" and just try to understand "How".
I know there is a post on this forum (saw it 2 days ago) that said that if you want to update as you leave a grid row, you use Dynamic List and its partner (whatever that is). The post went on to say that if you don't want the grid to auto post to the database as you leave the UI Grid Row, that you use Editable Root List and an Editable Child. While it baffled me, I wasn't having success doing what I was doing so I gave it a try. It doesn't work -- as you stated, its a mix match of types.
I still don't really get what I need to use. Our UI, for nearly all screens of a similar nature, use a Save button and thus we want to stay consistent. However, I cannot have a EditableRoot and an EditableChildList/EditableChild collection on it becaue the Editable Root save will change the concurrency flag and mess up the multi-user situation.
As stated above, the situation is that I have a list of tasks that multiple users on multiple machines need to edit. Each user will only operate on tasks they have started and others will work on other tasks. Each machine needs to be able to save the list and update all tasks that have changed on that machine. On another machine, their save needs to update all the tasks that changed there. Is there a set of CSLA objects that can support this?
As an aside, it seems odd to me (here I am asking Why again) that the CSLA framework is somewhat tightly coupled to the UI implementation with regards to Dynamic types. OUR patterns and pratices are, to every extent possible, decouple the implementation of the UI from the business and its data. We are using MEF, WPF, CSLA, DAL's and other technologies and patterns to avoid the business layer from needing to be aware of UI implementation and here is CSLA having the business layer respond to specific UI events. Not meaning to be critical only seems like a departure.
Oh, thank you for allowing me to edit my post! :) Is there a summary of the CSLA types, and what they work on/with? I know the book exists and have been through it a great deal, but a "site map" of the various CSLA objects all together (similar to the .NET library wall map that occasionally gets published). While the book can be great, there are somethings that I cannot find. I have seen in the book Dynamic Root List and Dynamic Root; however, on the forum there are mention of other Dynamic ... Base that I haven't found in the book. Just looking for a quick reference. Thanks
CSLA is designed to support the creation of business objects that match the user scenarios (stories, use cases - whatever you want to call them) necessary for the application to meet the needs of the user. This is behavioral responsibility-driven object design.
Of course the UI is also designed to support the user scenarios. So it shouldn't be surprising to find that the object model and the UX are similar - they are both designed around the user scenario.
This is _unlike_ a typical ORM or data model, which isn't designed around user scenarios, but instead is designed around data integrity and the ability to use data effeciently across _many_ user scenarios. Totally different design priorities.
To your concurrency question - that is a challenge in _any_ modern platform. This is because all modern platforms assume n-tier or SOA architectures, and so don't lock data in the database while it is used by a user. Additionally, modern platforms (for the past 17+ years) assume stateless servers, and exist in a networking environment where servers can't arbitrarily contact clients (because clients often have non-routable IP addresses).
The problem isn't unique to CSLA, nor are the array of solutions. Sadly, none of the solutions are particularly easy to implement.
The 'Using CSLA 4: Data Access' book shows how to implement optimistic concurrency using timestamp values. This is the most common, and usually most efficient, solution for concurrency.
But it sounds like you also want change notification across clients. That's a harder problem to solve, because the .NET platform doesn't provide a built-in solution for all the networking issues you'll face. What you need is a publish/subscribe technology that can communicate with non-routable IP addresses. Microsoft _does_ have one solution - the Azure Service Bus. But to use that you need to use Azure (fwiw, the service bus is _really_ cool, and if you are open to using Azure you should look at it!!).
The most common solution is to implement what's called "long polling" from the client. You can do this by using one of the WCF HTTP dual channels (not with the data portal - but with your own service), because they implement long polling to achieve efficient bi-directional communication between a client and server.
You can implement it yourself too - it isn't that terribly hard. Basically the client makes a service call with a long timeout (90 seconds or so). If the service has data for the client it returns it, and the client immediately re-calls the service. If the service doesn't have data, it doesn't return, allowing the client to timeout after 90 seconds. The client then re-calls the service.
This keeps the polling volume low (little overhead), and results in essentially instant transmission of data from the server to the client.
The UI guys are handling the freshness of the loaded objects and that sort of thing. I am only baffled by which meta-types (Editable Root List/Editable Root, Dynamic Root List/Dynamic Root, etc) that I should use to support the UI developers. I just need a list/object pair that I can load and save where it only saves the dirty objects from the list and where it doesn't update a concurrency flag on some parent object that causes issue with the other lists on the system. This is also not a web app. We actually use the timestamp of SQL Server for our concurrency and not a datetime stamp. The timestamp is handled by SQL Server vs our having to manually handle datetime and throw errors.
In earlier versions of CSLA, I recall the "Update" call of an Editable Root List to check for "is dirty" when saving the parent object and thus not breaking concurrency; I suppose we could use that approach. Thus the root object doesn't get updated but its child objects that are dirty could get updated?
I dunno! This seems like an outlier scenario.
If you are following the techniques shown in the samples and in the 'Using CSLA 4' books, when you save an editable root list, only the child objects that are dirty will be saved to the database. If the list itself saves any data to the database, that would be becuase your DAL did it - clearly your choice.
The way editable root list and editable child objects work hasn't changed in any meaningful way since 2001.
Well, that goes back to my original post then. It indicated that I was using an Editable Root List with Editable Child objects and the save fails because I "cant save a child object directly". I am calling save on my Editable Root List which itterates over the child objects and calls save on them.
Another poster indicated that I was mixing types and probably shouldn't.
I will dive back into the book(s), but my book search thus far has not proven helpful - thus I am on the forums.
It is true, you can't save a child directly. But when you save the list, only the changed child objects (new, dirty, or deleted) will be updated by the DAL. All changed child objects are saved as a batch, normally within a transaction on the server.
AH HAH! I was in the wrong book
Copyright (c) Marimer LLC