- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
Question on Saving (possibly very newbie-ish)
Joined: 22-Feb-2005
I can't seem to find this exact example in the documentation, and I searching through these forums has not produced the answer either (probably bad keywords). Anyway . . .
For our current project, we are using LLBL Gen for data access only. We use the generated objects to populate business objects that have no knowledge of LLBL Gen in a layer we call "DAO". This separation is a 100% requirement of the system.
The LLBL objects populate the BO and then fall out of scope (i.e. stateless). When the DAO gets the BO back, it has to map it back into the LLBL Gen object and then save it to the database.
For this example, I have a User BO and this BO has a collection of Group BOs that represent a relationship table between User and Group.
So I might create this BO for a process that needs it (this is all pseudocode):
UserBO.Id = 1 UserBO.Group[0].ID = 10 UserBO.Group[1].ID = 20 UserBO.Group[2].ID = 30
When the process gives it back, it has one Group object that was removed, and one that was added:
UserBO.Id = 1 UserBO.Group[0].ID = 10 UserBO.Group[1].ID = 30 UserBO.Group[2].ID = 40
Now I want to save that whole list properly, with both the delete and the insert, keeping in mind that it COULD be just a delete (only two groups came back) or just an insert (four groups came back).
How can I accomplish this short of loading a LLBL User object wth group relationships, then traversing both collections and comparing them to see the differences?
I'm sure this is a total newb question but I can't seem to figure it out.
Thanks much,
Phil
psandler wrote:
I can't seem to find this exact example in the documentation, and I searching through these forums has not produced the answer either (probably bad keywords). Anyway . . .
For our current project, we are using LLBL Gen for data access only. We use the generated objects to populate business objects that have no knowledge of LLBL Gen in a layer we call "DAO". This separation is a 100% requirement of the system.
The LLBL objects populate the BO and then fall out of scope (i.e. stateless). When the DAO gets the BO back, it has to map it back into the LLBL Gen object and then save it to the database.
For this example, I have a User BO and this BO has a collection of Group BOs that represent a relationship table between User and Group.
So I might create this BO for a process that needs it (this is all pseudocode):
UserBO.Id = 1 UserBO.Group[0].ID = 10 UserBO.Group[1].ID = 20 UserBO.Group[2].ID = 30
When the process gives it back, it has one Group object that was removed, and one that was added:
UserBO.Id = 1 UserBO.Group[0].ID = 10 UserBO.Group[1].ID = 30 UserBO.Group[2].ID = 40
Now I want to save that whole list properly, with both the delete and the insert, keeping in mind that it COULD be just a delete (only two groups came back) or just an insert (four groups came back).
How can I accomplish this short of loading a LLBL User object wth group relationships, then traversing both collections and comparing them to see the differences?
If I understand you correctly, you should be able to fetch the user entity and its group entity objects, for example using a prefetch path, and then do the following: traverse the group entities from front to back, and check if these are in the groupBO collection. If they are, remove the groupBO from the groupBO collection. If they're not, they're deleted and you add them to a new groupentity collection.
Then you traverse teh groupBO collection to see if there are any groupBO's left. If so, create new groupentity objects in the userentity's group collection.
then create a transaction (or if you're using adapter, create an adapter and start a transaction) and first save the User entity recursively, then delete the collection to which you added the entities which aren't present in the groupBOs, either by calling DeleteMulti() (in selfservicing) or DeleteEntityCollection (in adapter).
Joined: 22-Feb-2005
Otis wrote:
psandler wrote:
I can't seem to find this exact example in the documentation, and I searching through these forums has not produced the answer either (probably bad keywords). Anyway . . .
For our current project, we are using LLBL Gen for data access only. We use the generated objects to populate business objects that have no knowledge of LLBL Gen in a layer we call "DAO". This separation is a 100% requirement of the system.
The LLBL objects populate the BO and then fall out of scope (i.e. stateless). When the DAO gets the BO back, it has to map it back into the LLBL Gen object and then save it to the database.
For this example, I have a User BO and this BO has a collection of Group BOs that represent a relationship table between User and Group.
So I might create this BO for a process that needs it (this is all pseudocode):
UserBO.Id = 1 UserBO.Group[0].ID = 10 UserBO.Group[1].ID = 20 UserBO.Group[2].ID = 30
When the process gives it back, it has one Group object that was removed, and one that was added:
UserBO.Id = 1 UserBO.Group[0].ID = 10 UserBO.Group[1].ID = 30 UserBO.Group[2].ID = 40
Now I want to save that whole list properly, with both the delete and the insert, keeping in mind that it COULD be just a delete (only two groups came back) or just an insert (four groups came back).
How can I accomplish this short of loading a LLBL User object wth group relationships, then traversing both collections and comparing them to see the differences?
If I understand you correctly, you should be able to fetch the user entity and its group entity objects, for example using a prefetch path, and then do the following: traverse the group entities from front to back, and check if these are in the groupBO collection. If they are, remove the groupBO from the groupBO collection. If they're not, they're deleted and you add them to a new groupentity collection.
Then you traverse teh groupBO collection to see if there are any groupBO's left. If so, create new groupentity objects in the userentity's group collection.
then create a transaction (or if you're using adapter, create an adapter and start a transaction) and first save the User entity recursively, then delete the collection to which you added the entities which aren't present in the groupBOs, either by calling DeleteMulti() (in selfservicing) or DeleteEntityCollection (in adapter).
In the case of a relationship table, would it not be better to delete the whole collection and then re-add all the records? This would be less code, but might be worse from the perspective of making database calls.
The other way I was thinking I could handle it would be to create predicate expressions to delete (and possibly create as well) these relationship records:
(pseudocode) Delete from user_x_group where UserID = UserBO.ID and GroupID not in (UserBO.GroupBO.IDCollection)
I somehow think I am overcomplicating the issue. If I were using a datagrid to directly bind to a collection, and allowed the user to add and delete, how would I reconcile this in the LLBL collection (assuming I did not keep the LLBL object in state)?
I love the product, by the way. Not a day goes by where I don't have a "wow" moment with it.
psandler wrote:
In the case of a relationship table, would it not be better to delete the whole collection and then re-add all the records? This would be less code, but might be worse from the perspective of making database calls.
That's another option, I thought you wanted to do an 'in place' update . You can delete entities in one go, for example, in adapter by using adapter.DeleteEntitiesDirectly(), which would first remove all the current entities, and then you can just add new ones.
. DeleteEntitiesDirectly uses a single DELETE query.
The other way I was thinking I could handle it would be to create predicate expressions to delete (and possibly create as well) these relationship records:
(pseudocode) Delete from user_x_group where UserID = UserBO.ID and GroupID not in (UserBO.GroupBO.IDCollection)
I somehow think I am overcomplicating the issue. If I were using a datagrid to directly bind to a collection, and allowed the user to add and delete, how would I reconcile this in the LLBL collection (assuming I did not keep the LLBL object in state)?
It's a bit overcomplicated, but I think that's because you have that requirement of using your own BO's.
The entity collection objects don't see a removal of an entity from it as 'delete that entity', as removing an entity from a collection is ambiguistic: what to do is unclear. So you can track them with a Unit of work class, and use a collection to which you add the entities to delete and delete them in one go by using the UnitOfWork class' commit. This can be handy if the user after a long session of removing entities decides it's not what he wants and clicks cancel.
This is a tricky situation though. It involves state tracking for a live collection and a graph of objects, and I haven't found a solid solution to have an in-memory versioning system for that (so you go into a form with a graph, the user changes a lot of entities, then decides to cancel, and how do you roll back to your initial state..). Please do a search on Unit of work on the forum, various threads pop up with discussions about it and perhaps will give you ideas how to solve your problem, as it's something more people have dealt with
I love the product, by the way. Not a day goes by where I don't have a "wow" moment with it.