Generic list of Editable Root objects?

Generic list of Editable Root objects?

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


dagware posted on Saturday, November 22, 2008

I want to get a bunch of editable business objects from the database. I want to do it in one Data Portal call (they come from a single SELECT statement). But I don't want the objects to be "child" objects of a CSLA list -- I want them to be stand-alone root objects.

The reason is irrelevant. Can we please just assume I have good reasons, and not get into whether this is a good idea or not? Please? Thanks. :)

So I was thinking of using a Command object that returns a generic List<> of the root business objects. Does this sound feasible, or is there some reason this won't work?

Thanks in advance.

Dan

RockfordLhotka replied on Saturday, November 22, 2008

This is the purpose behind the EditableRootListBase base class in version 2.1 and higher.

You should be aware that this class is primarily intended to support in-place grid editing with data binding, but it can be used outside a data binding scenario as well (you just need to manually call the SaveItem() method to save individual root objects as appropriate).

dagware replied on Saturday, November 22, 2008

Thanks for the reply, Rocky. The reason I didn't consider the ERLB is because once I get the objects, I don't want them tied to anything.

I've just spent 45 minutes (seriously!) typing various explanations of why I'm doing this, and each of the explanations is too long-winded to be of much use. This may indeed mean that I'm trying to do something the wrong way -- I've found that most of the time, if I can't explain things clearly, then I'm doing something wrong.

However it may also be that it really is this complicated. So, I'm actually going to type one of these long-winded explanations and see if you think I'm going about it the wrong way.

Caveat: I work for a large company, and sometimes you have to work with things the way they are, whether you like it or not. This is one such situation.

We have two sources of information about Application Users. One is from our Authentication Store, which is a set of web services. The other is from our Application Users Store, which is a SQL database. For the purposes of this discussion, I'll refer to them as Web Service objects and SQL objects. I want to combine them into one list of Users that contains both sets of information. This combined list will also allow users to be added and removed from Applications, and the proper routines in both sources have to be called.

To make matters more complicated, the Data Portal routines for the Web Service objects always have to RunLocal. It would be nice if the Data Portal routines for the SQL objects could run in a remote data portal which may not be possible, and I can live with it if it isn't possible, but if there's a way, I'd prefer to do it.

Another issue is that the Web Service doesn't have any way to roll back changes. So if I'm saving Web Service objects and at some point I run into an error, I can't roll back what was saved before the error. That means I also want to save the SQL objects up to that point also. I realize that I can't guarantee 100% synchronization here, but the truth is that the SQL database saves will almost never fail, whereas the Web Service calls actually might fail from time to time. And I can handle the objects being out of sync the next time the list is loaded, so it's less of a deal than you might think.

So what I want to do is get both sets of lists of users, and combine them together to present them in a UI. The user of the UI should never know or care that they came from two different places (although if they get out of sync, the user may have to make some decisions, but let's leave that out for now).

Soo, to make a long story long, here's the point: I was thinking I'd get the list of users from the Web Service, then get the list from the SQL database, and place each SQL object in a property of each Web Service object. Then when each Web Service object is saved, it would save the SQL object also.

Of course now that I've typed all this, I realize that the only way I can have the SQL objects run in a remote data portal is to put them in a separate list and call that list's Save separately. So I guess I could mark each SQL object so it knows its corresponding Web Service object was saved successfully. Then if there's an error saving the Web Service objects, I can still try to save the SQL objects up to that point.

By the way, I've written the Insert, Update and Delete routines so they never assume the data is in the state they expect. For example, the SQL Insert stored procedure checks to make sure the record hasn't already been inserted. Same for all the SQL and Web Service IUD routines. So if there's ever an exception during the Save, and the UI reverts to the original list before cloning, and then tries to save it again, the routines will work correctly.

So I guess you can see why this is so complicated. Any advice? Getting a new job is not an option... ;p

Dan

dagware replied on Sunday, November 23, 2008

I think I figured out how to handle this. In short:

After loading the Web Service objects, I get a read-only list of SQL objects. I populate some fields in the Web Service objects with values from the SQL objects, then discard the SQL objects.

In the Web Services object list, in the Save() method, I create an empty list of "SQL Update" objects, then I call the base Save(). During the save, my Web Service objects add SQL Update objects to the list as needed. When the base Save() is done, I call the SQL Update object list's Save() method to apply the SQL updates.

There's a couple of nice things about using the SQL Updates object list. The first is that since it's called after the Web Service's base Save() method, it happens in its own Data Portal, so it can use a remote data portal even if the web service objects don't. The second is that I can save the SQL Update objects regardless of whether an exception occurred while saving the Web Service objects.

So, I think this is going to do exactly what I need.

Dan

Copyright (c) Marimer LLC