2010-05-07 1 views
1

J'utilise des variables de session dans un service Web pour maintenir l'état entre les appels successifs de méthode par une application externe appelée QBWC. Je mis cela en décorant mes méthodes de service web avec cet attribut:un comportement inattendu de l'objet stocké dans le service Web Session

[WebMethod(EnableSession = true)] 

J'utilise la variable de session pour stocker une instance d'un objet personnalisé appelé QueueManager. Le QueueManager possède une propriété appelée ChangeQueue qui ressemble à ceci:

[Serializable] 
public class QueueManager 
{ 
    ... 
    public Queue<QBChange> ChangeQueue { get; set; } 
    ... 

où QBChange est un objet métier personnalisé appartenant à mon service Web.

Maintenant, chaque fois que je reçois un appel à une méthode dans mon service web, j'utiliser ce code pour récupérer mon objet QueueManager et accéder à ma file d'attente:

QueueManager qm = (QueueManager)Session[ticket]; 

puis-je supprimer un objet de la file d'attente, en utilisant

qm.dequeue() 

puis-je enregistrer l'objet gestionnaire de requête modifiée (modifiée car elle contient un objet moins dans la file d'attente) Retour à la variable de session, comme suit:

Session[ticket] = qm; 

prêt pour le prochain appel de méthode de service Web en utilisant le même billet.

Maintenant, voici la chose: si je commente cette dernière ligne

//Session[ticket] = qm; 

, le service Web se comporte exactement de la même manière, ce qui réduit la taille de la file d'attente entre les appels de méthode. Maintenant pourquoi est-ce?

Le service web semble être une classe de mise à jour contenue sous forme sérialisée dans une variable de session sans être demandé. Pourquoi ferait-il ça? Lorsque je désérialise mon objet Queuemanager, la variable qm contient-elle une référence à l'objet sérialisé dans la variable Session [ticket] ?? Cela semble très improbable.

Répondre

0

Tous les types de référence (comme les classes) sont stockées dans la mémoire comme référence et état de session est également (normalement) stocké dans la mémoire, mais peuvent également être stockés dans un fichier ou une base de données. Lorsque vous stockez des types de référence dans Session, vous devez presque toujours vous assurer qu'ils sont également sérialisables.

QueueManager est un type de référence, donc tout ce que le Session[ticket] fait contient une référence en mémoire. Vous n'avez pas besoin de re-assigner comme la variable Session se IS l'élément que vous modifiez.

Ceci est juste une version simplifiée de ce que vous faites:

Session["Foo"] = new Bar(); 
Bar rar = (Bar)Session["Foo"]; 
rar.Count = 1; 

if (((Bar)Session["Foo"]).Count == 1) 
{ 
    // Great success! 
} 
+0

Je vois. J'avais l'impression que l'objet entier était réellement sérialisé lorsqu'il était placé dans une variable de session. Qu'en est-il d'un objet dans ViewState, alors? Est-ce complètement sérialisé entre les appels de page, ou ViewState détient-il juste une référence à l'objet? Et en supposant que ce que vous dites est vrai, alors pourquoi est l'attribut Serializable nécessaire pour placer un objet en session, alors? – draconis

+0

Il n'est pas toujours obligatoire que la classe soit sérialisable pour être en session.Cela dépend de la configuration de votre gestion de session sur le serveur. Je crois que cela fonctionne de la même manière à travers viewstate, cependant la classe DOIT être sérialisable car ViewState (StateBag) sérialise et désérialise réellement l'objet. Lorsque vous appelez et lancez la classe via ViewState, elle est désérialisée. – GenericTypeTea

+0

Votre explication est-elle valide uniquement pour l'état de la session en cours de traitement ou est-elle générique? Si l'état de la session était configuré en mode Out-of-process ou en mode SqlServer, serait-il toujours vrai que seule une référence à un objet est conservée dans une variable de session? – draconis

Questions connexes