This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
I have been using LightSpeed (mostly on the retrieving data side) for a about a year, with good success, so my experience saving data to the database is limited. The folks that setup the project before I started working on it created a set of Manager classes that handle creating new entities (i.e. Profiles). Each manager class has a Create method which instantiates a new entity and adds it to the UnitOfWork. The SessionMgr is a singleton class.
Based on this design, I assumed that if I created a Profile entity apart from the Manager's create method, it would NOT be included in the UnitOfWork. However, this appears to not be the case. Here is my scenario: I have a fairly complex MVC 2 user interface that allows a user to create a Profile with a lot of data. All the data is stored client side in javascript objects. Just before the user selects save, they can "Preview" the profile, which passes all the profile data to a page which constructs a Profile object in memory from the Javascript data. The purpose of the profile is beyond the scope of this question, but it's functionality requires that I retrieve data from the database and present it back to the user based on the layout of their profile. Since the user hasn't saved this profile yet and may want to make changes, I fill a Profile entity and children entities from the Javascript data with then intention of NOT including it in the UnitOfWork. Once the user selects to save the profile, I repeat the process but instead create entities in the UnitOfWork (with the Create methods in the Managers classes). I am able to create new profiles and edit existing profiles wonderfully following this method until I attempt to use the Preview functionality. Despite everything I expected, a newly created Profile object appears to be "magically" added to the UofW. I can tell, because, I get a copy of the profile for every Preview I perform in addition to the actual saved profile, when I click Save. Once I found the correlation to the Preview and the number of duplicates, I thought, "Oh LS must be adding the entities for me". I should be able to tell it to remove the entities from the UofW. Therefore, just as the preview functionality is complete, I process through the parent Profile object and all children objects and remove them all from the UnitOfWork using the Detach() method. I have also tried using the Remove() method. Neither appears to be working as I still get duplicates. Sometimes I get duplicates when I: 1. Create a new profile, preview it a few times, and save. 2. Create a new profile, preview it a few times, save, then edit it again, make no changes, but finish the save process (no additional previews). I am at a complete loss. What do I need to do to make Profile and children entities NOT included in the UofW in certain situations? Thank in advance. Donovan |
|
|
Hello Donovan, LightSpeed adds a new entity to the unit of work under two circumstances:
(In both cases, it cascades to any other entities associated with the new entity. E.g. if A (new) has an association to B (new), and C has been loaded from the database, then calling C.As.Add(A) will add A to C's unit of work, and will also add B to C's unit of work via the cascade.) So it is absolutely possible to create a Profile entity and it will not be associated with any unit of work, unless you do one of these two things. It seems like you are adding Profiles to the UOW as part of your preview functionality, perhaps because you are associating the tentative Profile with a database object (say, a Customer). You should check your preview code for such an association. However, this should not matter if you throw out that unit of work once the preview request completes. Is it possible that the inherited code is using a unit of work per session rather than a unit of work per request? That would explain why you sometimes see 'preview-stage' profiles accumulating in the UOW over the course of multiple requests. Your mention of detaching the entities from the UOW suggests this could be the case, because if you were using UOW per request you would not need to detach the entities (they would just disappear along with the UOW at the end of the request). If you think you do have 'unit of work per session,' then the best solution is to replace that with 'unit of work per request.' This will avoid any potential for entities to accumulate over the course of multiple previews, and it will also eliminate a whole class of fault tolerance/failover problems. You should be able to use PerRequestUnitOfWorkScope to make this change fairly painless. If however you can't or don't want to do this, then removing association code from the preview code should suffice. As long as you never associate the preview Profile with a real Customer, then it will never get into the UOW. Hope this makes sense -- let us know if you need any more info. |
|
|
Thanks for the informative response Ivan. I work with Donovan and have researched the SessionMgr classes. The person who originally wrote those classes isn't available any more and the class's complexity makes me uneasy about trying to switch from a session to request based UnitOfWork under the current circumstances (We're under the gun to deploy the application). You didn't comment on why Donovan's attempt to detach or remove the temporary profile didn't succeed in making it go away. It seems that should work. Is there something you didn't mention that would account for this? Thanks Steve |
|
|
Hi Steve and Donovan, I know how you feel about tweaking complex infrastructure classes! Detaching or removing the temporary profile should work, and without knowing your application internals it's hard to say why it wouldn't. My guess is that it relates to associated entities. Perhaps SessionMgr is reloading the same Customer object (that the preview Profile was attached to) into the UOW. Detaching the Profile removed it from the UOW but didn't break its associations, so when Customer rejoins the UOW it brings its Profiles with it -- including the preview Profile(s). Your best bet is probably to rework the preview code so that either:
By doing one of these things you avoid entangling your Profile with the session-level UOW. If you really must use SessionMgr to work with your preview Profile objects then Detach or Remove should work to get a Profile out of the UOW and you will need to look into what SessionMgr is loading and what associations it has to Profile objects, but I fear this will probably prove quite hard to disentangle (LightSpeed isn't really built around a design of moving stuff in and out of a UOW over a long period of time). Another possibility is to create a transient IsPreview field on the Profile object. Then override Profile.OnSaving to cancel the save (for that Profile) if IsPreview is true. That would still result in your Customer / SessionMgr / UOW accumulating unwanted preview profiles, but at least you could avoid them being saved to the database. |
|
|
I agree the problem lies with associating the Profile with "live" entitites, because I am associating the profile with Members in at least two places (Steve: Criteria -> Contributor -> Member and possibly the owner of the profile). Option two seems like the best choice. Creating the Profile object and any dependent entities from a temporary UnitOfWork that can be thrown away when we are finished previewing, should be simple to implement. Thanks Ivan. Donovan |
|
|
Ivan, We went with the option to create a temporary Unit of Work and associate all the entities related to the preview process with that UOW. Everything appears to be working nicely. Thanks for the help. Donovan |
|