Using .NET proxies to update row without getting it first th

Posted by Admin on 22-Feb-2010 08:25

OpenEdge 10.1C

We create a .NET proxy to some procedures that take temp-tables as parameters.  For example, the signatures for a couple of the generated .NET methods are...

public string GetFaqByObj(decimal userSessionObj, decimal faqObj, out FaqDataTable faqTable, out string errorMessages)

public string SaveFaqs(decimal userSessionObj, ref FaqDataTable faqTable, out string errorMessages)

If we use GetFaqByObj to load up an instance of a FaqDataTable then modify it and pass it to SaveFaqs then everything works just fine.  However, there are some cases where it would be desirable to build up an instance of a FaqDataTable on the .NET side with rows we'd like updated and then pass that FaqDataTable instance to SaveFaqs.  We've attempted this kind of approach but the rows are not modified.  Any thoughts on why this wouldn't work or suggestions about what we ought to look at?

In case it helps, we're using AutoEdge-inspired code to save the temp-table as a part of a dataset.

All Replies

Posted by Thomas Mercer-Hursh on 22-Feb-2010 11:04

In case it helps, we're using AutoEdge-inspired code to save the  temp-table as a part of a dataset.

Probably not the best start ...

Posted by Admin on 22-Feb-2010 11:07

Thanks for the reply Thomas, can you expand on that a bit or point me at something that expands on it?  I'm not sure what to take from it.

Posted by Thomas Mercer-Hursh on 22-Feb-2010 11:38

This is a starting point  I have lot more in the works, but can't promise exactly when it will show up ... things seem to always take longer than they should.  You might also want to check out the OO forum for the thread on the Model-Set-Entity pattern.  That clearly is head-and-shoulders ahead of any of the PSC-related patterns using PDS.

The one-liner is, IMHO, that a PDS does not provide a good basis in the business logic for the best OO principles and passing a PDS between DL and BL is not good layer seperation of concern.  Check out the other OO articles on my site and think about the patterns you are using in terms of the design principles there.

Posted by Admin on 22-Feb-2010 14:10

Everett, please be aware that not everybody outside the PSC organization has such a negative view about ProDatasets. Certainly the AutoEdge code might not be the best pattern or sample but that does not mean that one should ban passing ProDatasets completely. They are still a very efficient part of the language and have their use in procedural and object oriented code, especially in combination with .NET

(Now I'm a little afraid about the responses I may receive )

Back to your original question: There is little information about how you're passing the temp-table from the .NET client to the AppServer. I'm pretty sure that you have validated that the temp-table (DataTable) had changes on the .NET side? (i.e. GetChanges() does not return an empty table).

One thing that comes into my mind is the fact that in the ABL change information requires the temp-table being passed as part of a (Pro)Dataset - that's a little different from .NET where a DataTable alone may hold change information. You're just writing that you're passing a table, so that might be an explanation. Second, make sure that the ProDataset member temp-table has a before-table attached (DEFINE TEMP-TABLE .... BEFORE-TABLE).


Posted by Thomas Mercer-Hursh on 22-Feb-2010 14:26

I'm not negative about PDS.  They are fine and dandy in their place.  Two places where they are particularly useful is as a data message packet between ABL sessions and as a local data source within the data layer to provide a more suitable structure according to the OO structure when that differs from the RDB structure.

Where I differ from PSC models is primarily in two places.  One is in using the PDS as a data message packet between the DL and BL within the same section.  To me this is a far higher level of coupling than one wants.  The other is in any of the four models which use a PDS as the repository of data in and OO programming environment, either by identifying one entity in the set as the "Current" entity or, as in the M-S-E pattern, but spawing business entity objects which have no data of their own, but which point back to the PDS in the Model object for their data.  To me, this is a sign of continuing to think in terms of RDB models, not OO models, thus losing the best benefits of the OO approach.

Posted by Admin on 22-Feb-2010 14:46

To me, this is a sign of continuing to think in terms of RDB models, not OO models, thus losing the best benefits of the OO approach.

As of today nobody has even closely succeeded in convincing me that giving up the benefits of RDB models in the business logic layer is that much better than giving up on the benefits of OO approaches.

The ABL is incomparable effective in working with RDB models, that I believe it's not possible to 1:1 adopt models that are good for other (not that effective) languages like Java. Especially as long as there are no built in List objects and objects can't be used as a message between different sessions without providing your own serialization mechanism or using an RDB construct like temp-tables or ProDatasets as a way of a serialization.

Good think is we have both choices. Hard thing is, everybody needs to make his own decision. I've made mine. It may change when the language evolves or requirements do changes. So far most projects I've been involved did require to still use a large portion of existing code which is RDB based (of course).

Posted by Thomas Mercer-Hursh on 22-Feb-2010 15:56

Well, now we are seriously hijacking this thread, so if we continue, we should probably move it over to a new thread on the OO forum.

As you know, I am prepared for the rules for best practice in OOABL to be somewhat different than the rules for any given 3GL OO, but over and over when I think I have found a case, more often than not I end up deciding that the RDB mentality is not actually better and loses benefits of the OO mentality, so I end up sticking with a more pure OO approach.  I know that is not to everyone's taste and one can certainly do good work without it, but I do think it is worth educating ourselves on the difference so that the choice can be made intelligently.

As for language deficiencies, I have no interest in sending objects across the wire and think that people who do so in 3GL OOs are not practicing the best separation of concern.  Minimal data packets is all I want to send between layers or subsystems to minimize coupling.

Yes, I would like a lighterweight collection mechanism, but I suspect that I would be happy enough with PLO support in work tables for that.  Once you get to Map objects, might as well use a TT.

Posted by Admin on 22-Feb-2010 16:07

Well, now we are seriously hijacking this thread, so if we continue,

we should probably move it over to a new thread on the OO forum.

At least I've tried to stay on track with the original post in my

first reply here...

Posted by guilmori on 23-Feb-2010 13:57

Does running this prior to updating the datatable helps ?

Progress.Open4GL.ProDataTable.SetBImageFlag(faqTable, true);

Posted by Admin on 23-Feb-2010 14:11



Thanks for the conversation guys.  I looked at the stuff Thomas pointed me at and I've appreciated the dialog.

I've got a foot in the Progress world and in the 3GL world so the dialog is relevant and timely.  As I'm working with the new OO features of the 4GL I've been trying to figure out how I might do some of the kinds of things I've done in data centric apps using NHibernate or LLBLGen Pro.  It seems like there should be a way to get the most of the object orientation and the relational database features at the same time.  I get the impression that's what Thomas is driving at.  I'll be keeping my eye on Thomas' work in this area.  A more purely OO approach is appealing on several levels.


I've seen the collections code.  Does it have any example of the persistence/hydration strategy you describe or are such examples available elsewhere?

Posted by Admin on 23-Feb-2010 14:12

Thanks Guillaume!

I'll give this a try and let you know.

Posted by Thomas Mercer-Hursh on 23-Feb-2010 14:29

As pointed to by my PUG Challenge talk, the model I will be discussing in a future whitepaper is one using PABLOs for business entity objects in the BL.  I see these being created by a factory in the BL based on a message data packet from the DL to minimize layer coupling.  The RDB to OO mapping will occur in the DL..  Thus, the BL will be pretty familiar OO in most respects except for some implementation details like using TTs to implement collections until such time as PSC gives us something lighterweight.  I will be experimenting with some things not usually found in a 3GL, like a generic SuperMap, which behaves like a Java Map class, but with multiple indexed values per object at the same time.

The collections code doesn't deal with persistence and I don't currently have sample code available that illustrates it.  Patience is required, unfortunately.  Unless, of course, someone would pay for some consulting and then it would come to the fore!  Funny how that works!

Posted by Admin on 23-Feb-2010 16:54

Ok, I think I may have answered my own question.

In the scenario I describe above we're doing something akin to an import.  The reason this doesn't work like we expect is that the default behavior for a DATA-SOURCE is to do data conflict checking against the buffer for the BEFORE table.  In other words, before changes are saved there's a check to see if the data in the database and that in the buffer are the same.  This is pretty standard part of an optimistic locking strategy and it's cool that you get it for free. Practically speaking, this means that unless you fill the DataTable with rows exactly matching database rows, execute the AcceptChanges() method on the DataTable and then make your changes, you'll get a data conflict when you execute SAVE-ROW-CHANGES.  You can modify this behavior by setting the PREFER-DATASET attribute of the DATA-SOURCE to TRUE and then SAVE-ROW-CHANGES will ignore the data in the actual database rows and accept the data from the TEMP-TABLE buffer.

So, you can do what I originally asked about but as I currently understand it, it's a bit tedious.  You have to...

  1. fill a DataTable instance with rows exactly as they are in the database (why not just go get them from the database if you have to do this)
  2. execute the AcceptChanges() method on the DataTable
  3. make your changes
  4. execute app server call to save the temp-table

If you haven't already, I'd consider checking out what Thomas has written and linked to above.  We're too time constrained to change course for this current project but I think we'll be looking into an approach like the one Thomas describes for our upcoming projects.

Thanks all.

This thread is closed