EntityCollection not being serialized?

Posts   
 
    
jookyone avatar
jookyone
User
Posts: 104
Joined: 25-Jan-2005
# Posted on: 27-Apr-2005 19:03:51   

Having a problem in my current project, where in a particular form we are retrieving an entity object with several related entities and entitycollections via prefetch paths. THe retrieval works just fine, all entities and collections related to the root entity are fetched correctly. Once the root entity is fetched, we are storing it in Session so that when the user clicks the Update button (after editing various fields in the form) we grab the entity from Session and assign the form values to the respective fields in the entity and related entities. There are 2 checkbox lists on the form, whose items are selected based on the records in the 2 related entity collections that were fetched previously. The problem is that when the Update() method is called, the code loops through the checkboxlists and for each item creates a new entity, sets IsNew to false, and checks if the associated entity collection contains that entity already. Then it either adds the new entity to the collection if the listitem is selected and the entity does not already exist in the collection or it adds the entity to a temporary entitycollection that is passed into the DeleteEntityCollection() method if the item is deselected and the entity does already exist in the collection.

The problem is that after the existing entity is updated after selecting some items in the checkboxlists--in this particular test case the existing entity did not initially have any items in either entitycollection--when the entity is retrieved from Session all the related entities are there with the updated fields, but the entitycollections show up as empty. I did a couple other tests to force a refetch of the entity on each postback, but anytime I grabbed the entity from Session the entitycollections where empty. Even if I did something like this:

Code in codebehind

ApplicationController controller = new ApplicationController();
ApplicationEntity application = controller.RetrieveApplicationWithRelatedEntities(applicationId, ApplicationRelations.OtherService, ApplicationRelations.Person, ApplicationRelations.SpecialStatus);
Session["Application"] = application;

//all entities and entitycollections that are fetched along with ApplicationEntity are currently
// in the application object--verified this during debugging session
ApplicationEntity appFromSession = (ApplicationEntity)Session["Application"];

// all entities are correct in appFromSession instance, but all EntityCollection objects are now empty


Exerpt of code in ApplicationController


/// <summary>
        /// Retrieves the ApplicationEntity by the specified applicationID. 
        /// The params collection is a array of ApplicationCollections enums that
        /// are passed in to specify which related Entity/EntityCollection objects you wish to have fetched along 
        /// with the ApplicationEntity object.
        /// </summary>
        /// <param name="applicationId">ApplicationId for the application to retrieve.</param>
        /// <param name="relations">ApplicationRelations enum. Specifies related entities to create prefetch paths for.</param>
        /// <returns>ApplicationEntity object containing any retrieved data.</returns>
        public ApplicationEntity RetrieveApplicationWithRelatedEntities(int applicationId, params ApplicationRelations[] relations)
        {
            DataAccessAdapter adapter = new DataAccessAdapter();
            ApplicationEntity appEntity = new ApplicationEntity( applicationId );
            IPrefetchPath2 prefetchPath = new PrefetchPath2( (int) EntityType.ApplicationEntity );
            for ( int i = 0; i < relations.Length; i++ )
            {
                prefetchPath.Add( GetPrefetchPathElement( relations[ i ] ) );
            }
            prefetchPath.Add( ApplicationEntity.PrefetchPathPerson ).SubPath.Add( PersonEntity.PrefetchPathAddress );
            adapter.FetchEntity( appEntity, prefetchPath );
            return appEntity;
        }
        
        /// <summary>
        /// Gets the prefetch path element for the specified ApplicationCollections enum.
        /// </summary>
        /// <param name="relation">ApplicationRelations enum.</param>
        /// <returns>IPrefetchPathElement2 object containing the prefetch path information for the specified relation.</returns>
        private IPrefetchPathElement2 GetPrefetchPathElement(ApplicationRelations relation)
        {
            switch ( (int) relation )
            {
                case (int) ApplicationRelations.ApplicationSpecialStatus:
                    return ApplicationEntity.PrefetchPathApplicationSpecialStatusCollection;
                case (int) ApplicationRelations.ApplicationStatus:
                    return ApplicationEntity.PrefetchPathApplicationStatus;
                case (int) ApplicationRelations.ChildRecon:
                    return ApplicationEntity.PrefetchPathChildReconCollection;
                case (int) ApplicationRelations.CombatDeterminationDecision:
                    return ApplicationEntity.PrefetchPathCombatDeterminationDecision;
                case (int) ApplicationRelations.CongressionalInquiry:
                    return ApplicationEntity.PrefetchPathCongressionalInquiryCollection;
                case (int) ApplicationRelations.DfasTransmittalLetter:
                    return ApplicationEntity.PrefetchPathDfasTransmittalLettersCollection;
                case (int) ApplicationRelations.Disability:
                    return ApplicationEntity.PrefetchPathDisabilityCollection;
                case (int) ApplicationRelations.DocumentType:
                    return ApplicationEntity.PrefetchPathDocumentTypeCollection;
                case (int) ApplicationRelations.IneligibleByUser:
                    return ApplicationEntity.PrefetchPathIneligibleByUserCollection;
                case (int) ApplicationRelations.IneligibleReasons:
                    return ApplicationEntity.PrefetchPathIneligibileReasonsCollection;
                case (int) ApplicationRelations.Inquiry:
                    return ApplicationEntity.PrefetchPathInquiryCollection;
                case (int) ApplicationRelations.Inventory:
                    return ApplicationEntity.PrefetchPathInventoryCollection;
                case (int) ApplicationRelations.Notification:
                    return ApplicationEntity.PrefetchPathNotificationCollection;
                case (int) ApplicationRelations.OtherService:
                    return ApplicationEntity.PrefetchPathOtherServiceCollection;
                case (int) ApplicationRelations.Reconsideration:
                    return ApplicationEntity.PrefetchPathReconCollection;
                case (int) ApplicationRelations.Responsibility:
                    return ApplicationEntity.PrefetchPathApplicationResponsibilityCollection;
                case (int) ApplicationRelations.SpecialStatus:
                    return ApplicationEntity.PrefetchPathSpecialStatusCollection;
                case (int) ApplicationRelations.StatusHistory:
                    return ApplicationEntity.PrefetchPathApplicationStatusHistoryCollection;
                default: // This is completely arbitrary--could have returned any collection
                    return ApplicationEntity.PrefetchPathApplicationSpecialStatusCollection;
                    ;
            }
        }

In case you are wondering, ApplicationRelations is an enumeration I created to make it easy for a developer to fetch the entity and specify a custom set of related entities/collections to fetch along with it.

Any ideas as to what is going on?

jookyone avatar
jookyone
User
Posts: 104
Joined: 25-Jan-2005
# Posted on: 27-Apr-2005 19:24:20   

This confirms a problem with the serialization/deserialization of EntityCollection objects, as the problem could not be repeated when, instead of grabbing the ApplicationEntity from Session, I refetched it from the database and executed SaveEntity(). This worked fine. So the problem lies with storing an entity with related entitycollections in Session.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 27-Apr-2005 23:19:42   

Storing an object in the session is not serializing hte object into the session. I'll check it out what's going on.

Frans Bouma | Lead developer LLBLGen Pro
jookyone avatar
jookyone
User
Posts: 104
Joined: 25-Jan-2005
# Posted on: 28-Apr-2005 13:41:27   

Otis wrote:

Storing an object in the session is not serializing hte object into the session. I'll check it out what's going on.

True for in-proc session state, but when using Sql Server for session storage you are using serialized references, right?

jookyone avatar
jookyone
User
Posts: 104
Joined: 25-Jan-2005
# Posted on: 28-Apr-2005 14:06:54   

Don't worry about spending any time looking into that just yet Frans, I'm going to run some more tests and get back to you--I don't want you to waste any of your time or anything :-)

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 28-Apr-2005 15:05:34   

jookyone wrote:

Don't worry about spending any time looking into that just yet Frans, I'm going to run some more tests and get back to you--I don't want you to waste any of your time or anything :-)

Oh no problem. I do know that serialization works, but it's always a mistery which type of serialization .NET will use behind the scenes.

I'm not sure which one it uses for out-proc database oriented session management for example. It's likely the same as the viewstate uses, which does work (but has some limitations with deep complex hierarchies as it can get confused and give up (.net code that is))

Frans Bouma | Lead developer LLBLGen Pro
jookyone avatar
jookyone
User
Posts: 104
Joined: 25-Jan-2005
# Posted on: 29-Apr-2005 01:40:49   

I figured out the issue, it was something completely unrelated to Session or serialization (of course). I've been looking at this code too much...need a break:-)

erichar11
User
Posts: 268
Joined: 08-Dec-2003
# Posted on: 29-Apr-2005 02:23:13   

could you elaborate on what the issue was?