存储在Web服务会话中的对象的意外行为

时间:2010-05-07 15:22:18

标签: asp.net session web-services

我在Web服务中使用Session变量来维护名为QBWC的外部应用程序在连续方法调用之间的状态。我通过使用以下属性修饰我的Web服务方法来设置它:

[WebMethod(EnableSession = true)]

我正在使用Session变量来存储名为QueueManager的自定义对象的实例。 QueueManager有一个名为ChangeQueue的属性,如下所示:

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

其中QBChange是属于我的Web服务的自定义业务对象。

现在,每当我调用Web服务中的方法时,我都会使用此代码来检索我的QueueManager对象并访问我的队列:

QueueManager qm = (QueueManager)Session[ticket];

然后我使用

从队列中删除一个对象
qm.dequeue()

然后我将修改后的查询管理器对象(已修改,因为它包含队列中的少一个对象)保存回Session变量,如下所示:

Session[ticket] = qm; 

使用相同的故障单为下一个Web服务方法调用做好准备。

现在就是这样:如果我注释掉最后一行

//Session[ticket] = qm;

,然后Web服务的行为方式完全相同,减少了方法调用之间队列的大小。那为什么呢?

Web服务似乎正在更新Session序列中包含的类,而不会被要求。为什么会这样做?当我反序列化我的Queuemanager对象时,qm变量是否在Session [ticket]变量中保存对序列化对象的引用?这似乎不太可能。

1 个答案:

答案 0 :(得分:0)

所有引用类型(例如类)都作为引用存储在内存中,并且会话状态也(通常)存储在内存中,但也可以存储到文件或数据库中。在Session中存储引用类型时,您几乎应该始终确保它们也是Serializable。

QueueManager是一种引用类型,因此Session[ticket]所做的就是在内存中保存对它的引用。您无需重新分配,因为Session变量本身 IS 您正在修改的项目。

这只是您正在做的事情的简化版本:

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

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